連想配列を用いた無作為な並べ替え
↓ このようなお題をいただいたので、挑戦してみた。
データをランダムに並べ替えてください。
今回の作戦は、こんな感じだ。
1. 並び変え用の通し番号を格納した、連想配列を作成する。
2. 1~15の中から一つ、無作為に自然数を取得する。
取得は、RANDBETWEEN関数を使用する。
今回は、例えば「9」を取得したとする。
3. 9番目のkeyの値「9」を用いて並べ替え。
元の配列の9番目の値を、並べ替え後の1番にセットする。
4. 辞書の9番目を除去(REMOVE)する。
このとき、辞書の「何番目」は繰り上がるが、key情報で見た場合
9は欠番となる。
5. 以降、2~4 の繰り返し。
ただし今度は1~15ではなく、1~14の中から一つ選ぶ。
今回は、例えば「11」を取得したとする。
辞書の11番目のキー情報は「12」であるため、12番目の値を
並べ替え後の2番にセットする。
これを3,4,5・・・と繰り返す。
実際のコード
Sub 並べ替え() ' 元データを配列に格納。 Dim SrcArray As Variant SrcArray = Range("A1:A15") ' 並べ替え後のデータを格納する配列。 Dim DstArray As Variant ' 元データの配列を格納することで、配列サイズを調整。 DstArray = SrcArray ' 「何番目」を格納する辞書。 Dim SortDict As Scripting.Dictionary Set SortDict = New Scripting.Dictionary Dim i As Long Dim iMax As Long: iMax = UBound(SrcArray) ' 「何番目」というキー情報のみ使用する。 ' 従って、アイテム情報は不問。今回はキー=アイテムとした。 For i = 1 To iMax SortDict(i) = i Next Dim temp As Long i = 1 Do ' RandBetween関数で、「1~辞書のキーの個数」の範囲にある数を ' ランダムに求める。 temp = WorksheetFunction.RandBetween(1, UBound(SortDict.Keys) + 1) ' 辞書のKeysは0始まりの配列として取得可能。tempは1始まりであるため、 ' 1引いている。 DstArray(i, 1) = SrcArray(SortDict.Keys(temp - 1), 1) ' 使用した「temp番目」を辞書から除去する。これにより、一度使用した ' 数は使われない。 SortDict.Remove SortDict.Keys(temp - 1) If i = iMax Then Exit Do Else i = i + 1 End If Loop Range("C1:C15") = DstArray End Sub
元データを格納した配列と、並べ替え後の貼り付け先を引数にすれば、
もう少し汎用性が上がると思う。
参考まで。