2016年2月6日土曜日

VB 項目をランダムに並び替える

通常、ListBox や ComboBox の項目は、探し出し易い様に、ある規則に基いて並んでいて欲しいですね。
ソートしたりして 順番を調整する事は多くても、 敢えて、 ぐちゃぐちゃ にする 機会 は少ない筈です。
しかし、WPF で ListBox を使い、 一覧形式で 画像を表示した場合など、 毎回、同じ 顔ぶれ が並ぶのに、辟易 したりします。
そこで、 項目の ランダム な並び替え を。


今回も、Internet 検索で、有益な情報を 戴きました。
先ずは、その お礼 を述べさせて戴きます。  何時も、お世話になっております!。.
件の ご投稿 は こちら。     配列やコレクションをシャッフルする(ランダムに並び替える) - Dobon.Net プログラミング道

自分で考えて書いていると、 Bug の山。  まともに、動きもしません!。
乱数を使えば良いのは想像がついても、 何時まで経っても答えが返って来なかったり、 オーバーフローで中断させられたり ... 。
トホホ の時間が流れて行きます。

序でに、 アルゴリズムを考えられた 数学者さん って、偉いですね。  感謝です。


さて、本題。

項目のランダムな並び替えは 以下の コード を基本に、 Project に見合った形に OverLoads して使われると良いと思います。

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim sampleArray(15) As Integer
        For n = 0 To sampleArray.Count - 1
            sampleArray(n) = n
        Next

        MakeShuffle(sampleArray)

        Me.TextBox1.Multiline = True      '以下、結果を表示
        Dim result As New System.Text.StringBuilder
        For i As Integer = 0 To sampleArray.Count - 1
            result = result.Append(i.ToString & "  " & sampleArray(i) & vbCrLf)
        Next

        Me.TextBox1.Text = result.ToString

    End Sub

    Private Overloads Function MakeShuffle(ByVal itemsRandomArray() As Integer)
        'Usage ; Before Using, Make Array With Items Count
        '       Dim sampleArray(Count - 1) As Integer
        '       sampleArray = MakeShuffle(sampleArray)

        If itemsRandomArray.Count < 1 Then
            Return Nothing
        End If

        Dim tc As Integer = Environment.TickCount   'Default Seed
        Dim dm As Integer = Date.Now.Minute
        Dim s As Integer = CInt(tc / dm)            'Set My Seed

        'Fisher-Yates shuffle Algorithm
        '                       Ref.; http://dobon.net/vb/dotnet/programing/arrayshuffle.html

        'Dim rng As New System.Random()             'Default Seed
        Dim rng As New System.Random(s)             'Set My Seed
        Dim n As Integer = itemsRandomArray.Length
        While n > 1
            n -= 1
            Dim k As Integer = rng.Next(n + 1)
            Dim tmp As Integer = itemsRandomArray(k)
            itemsRandomArray(k) = itemsRandomArray(n)
            itemsRandomArray(n) = tmp
        End While

        Return itemsRandomArray
    End Function

End Class

通常、項目は、 Collection や List で与えられるでしょうから、 それを当て嵌めます。

元の項目を確保して置き、暫定的に、別のものを作るなら、 コピーを操作する事になります。
その時は、 Index を、上記の手法で並び替えて、 それを基に、 コピーを作って行く方法もあります。

尚、SortedList の様に、Keys で元々並び替えているものを操作しても意味がありません。
この場合には、別の Generic な Collection 類(例えば List)に切り替えるか、
System.Collections.Specialized.OrderedDictionary の採用を検討するかになるでしょう。



0 件のコメント:

コメントを投稿