リストボックス内の並び替えに関して(文字列+数字)

タグの編集
投稿者 tetsu(素人レベルです)  (社会人) 投稿日時 2011/2/21 16:12:03
はじめまして。
早速ですが、質問があります。
環境はVB2005です。

任意のキーワードでフォルダを検索し、リストボックスへ表示するプログラムを作ったのですが、
並べ替えでつまづいています。

現状のソートは
*****A1
*****A10
*****A2
*****A3

ですが、これを
*****A1
*****A2
*****A3

*****A10

(*は任意の文字、数字です。)

としたいのですが、どうすればこの並びで表示できるでしょうか。
文字列と数字の組み合わせの場合の上記の様な並べ替えが分かりません。

分かる方いれば、すみませんが教えて下さい。
投稿者 shu  (社会人) 投稿日時 2011/2/21 21:39:00
> *****A1
> *****A10
> *****A2
> *****A3
前6桁と残りに分け、残りの部分を数値としてみてソートする
ということですか?

IComparerを実装したクラスを作るといろいろなソートが出来ます。
以下はList(of String)のソート例です。


ソート用クラス
    Private Class clsComp
        Implements IComparer(Of String)

        Public Function Compare(ByVal x As String, ByVal y As String) As Integer Implements System.Collections.Generic.IComparer(Of String).Compare
            '--- x, yを各々分離
            Dim x1 = x.Substring(0, 6)
            Dim x2 = CInt(x.Substring(6))
            Dim y1 = y.Substring(0, 6)
            Dim y2 = CInt(y.Substring(6))

            Dim intRet As Integer

            '--- 最初の部分を比較
            intRet = String.Compare(x1, y1)
            '--- 最初の部分が同じなら残りの部分を比較
            Select Case intRet
                Case 0
                    intRet = x2.CompareTo(y2)
            End Select

            Return intRet
        End Function
    End Class

    


    '--- データ追加
    Dim list = New List(Of String)
    list.add(~)
    list.add(~)
    list.add(~)
    list.add(~)
    '--- clsCompを使ってソート
    list.Sort(New clsComp)

投稿者 ヴァン  (社会人) 投稿日時 2011/2/22 09:28:12
もう少し条件を書いた方がいいです。

「*」は何文字なのか?

「A」しかないのか?

下位の数値は2ケタまでなのか?

投稿者 tetsu(素人レベルです)  (社会人) 投稿日時 2011/2/22 13:41:08
shuさん、ご教授有難うございます。
教えてもらった方法で試してみます、2・3日かかると思いますので、
また、結果を書き込みます。

ヴァンさん、ご指摘有難うございます。
*****の部分の文字数は対象によって可変ですが、
*****が検索キーの部分ですので、リストアップされる時点ではA1もA10も同じ文字が入ります。
*****のあとは英字1文字+数字2桁(max)、数字部なしもありです。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/2/22 16:02:26
各種ソートを行えるよう、 DataTable で管理するようにしてみました。

Imports System.Text.RegularExpressions

Public Class Form1
    Private table As DataTable

    Private Sub Form1_Load(ByVal sender As ObjectByVal e As EventArgs) Handles Me.Load
        table = CreateTable()

        AddRow("*****A1")
        AddRow("*****B1")
        AddRow("*****A10")
        AddRow("*****A2")
        AddRow("*****A3")
        AddRow("*****A")

        ListBox1.DisplayMember = "Value"
        ListBox1.DataSource = table

        Button1.Text = "昇順"
        Button2.Text = "降順"
        Button3.Text = "数字だけ降順"
        Button4.Text = "登録順"
    End Sub

    Private Sub Button1_Click(ByVal sender As ObjectByVal e As EventArgs) Handles Button1.Click
        table.DefaultView.Sort = "head, key, num"
    End Sub

    Private Sub Button2_Click(ByVal sender As ObjectByVal e As EventArgs) Handles Button2.Click
        table.DefaultView.Sort = "head DESC, key DESC, num DESC"
    End Sub

    Private Sub Button3_Click(ByVal sender As ObjectByVal e As EventArgs) Handles Button3.Click
        table.DefaultView.Sort = "head, key, num DESC"
    End Sub

    Private Sub Button4_Click(ByVal sender As ObjectByVal e As EventArgs) Handles Button4.Click
        table.DefaultView.Sort = Nothing
    End Sub


    Private ReadOnly Pattern As New Regex("(?<head>^.*)(?<key>[a-zA-Z])(?<num>\d{0,2}$)")

    Private Sub AddRow(ByVal value As String)
        Dim m As Match = Pattern.Match(value)

        Dim newRow As DataRow = table.NewRow()
        newRow("Value") = value
        If m.Success Then
            newRow("Head") = m.Groups("head").Value
            newRow("Key") = CChar(m.Groups("key").Value)
            If m.Groups("num").Length > 0 Then
                newRow("Num") = CInt(m.Groups("num").Value)
            End If
        End If

        table.Rows.Add(newRow)
    End Sub

    Private Shared Function CreateTable() As DataTable
        Dim tbl As New DataTable()
        tbl.Columns.Add("Value"GetType(String))
        tbl.Columns.Add("Head"GetType(String))
        tbl.Columns.Add("Key"GetType(Char))
        tbl.Columns.Add("Num"GetType(Integer))
        Return tbl
    End Function
End Class
投稿者 tetsu(素人レベルです)  (社会人) 投稿日時 2011/2/24 16:39:32
****部の文字数は可変であったため、 魔界の仮面弁士さんのDataTable での
処理をカスタムしながら何とか自分のプログラムに組み込むことができました。
みなさん助言有難うございます。


ただ、その先の部分でまたまた、つまずいています。
datatableでの処理でListboxにアップされたアイテムの中で、
任意選択されたものをstring型で取得しlabelへ表示したいのですが、
DataRowViewからstring型への変換が出来ませんとエラーになります。


エラー構文:Label1.text = ListBox1.SelectedItem


この部分に関して分かる方いれば処理のしかたを教えて下さい。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/2/24 17:51:47
ListBox1.DisplayMember = "Value"     '表示に使われる項目 
ListBox1.ValuelMember  = "Value"     'SelectedValue で返される項目 

上記のようにしておけば、ListBox1.SelectedValue でデータを得られます。


> DataRowViewからstring型への変換が出来ませんとエラーになります。
ListBox1.Items(0) や ListBox1.SelectedItem から得たい場合は、こんな感じで。

Dim rowView As DataRowView = TryCast(ListBox1.SelectedItem, DataRowView)
Dim row As DataRow = rowView.Row
MsgBox( row(列名) )
投稿者 tetsu(素人レベルです)  (社会人) 投稿日時 2011/2/24 18:15:58
魔界の仮面弁士さん、さっそくの回答、有難うございました。
教えてもらった方法で試し、全て解決しました!!!

型の理解など基本的な部分がまだまだ弱いので、これからもっと
勉強していきたいと思います。

みなさん、親切に色々とありがとうございました。