DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

配列やコレクションをシャッフルする(ランダムに並び替える)

配列をシャッフルし、要素をランダムに並び替える方法を紹介します。ここでは配列を例にしていますが、コレクションでも同じようにできるでしょう。なおここで説明している事柄は、「Coding Horror: Shuffling」を参考にしています。

Fisher-Yatesアルゴリズム

まず、Fisher-Yatesアルゴリズムによる方法を紹介します。この方法は非常に高速です。

VB.NET
コードを隠すコードを選択
'シャッフルする配列 
Dim ary As Integer() = New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

'Fisher-Yatesアルゴリズムでシャッフルする 
Dim rng As New System.Random()
Dim n As Integer = ary.Length
While n > 1
    n -= 1
    Dim k As Integer = rng.Next(n + 1)
    Dim tmp As Integer = ary(k)
    ary(k) = ary(n)
    ary(n) = tmp
End While
C#
コードを隠すコードを選択
//シャッフルする配列
int[] ary = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

//Fisher-Yatesアルゴリズムでシャッフルする
System.Random rng = new System.Random();
int n = ary.Length;
while (n > 1)
{
    n--;
    int k = rng.Next(n + 1);
    int tmp = ary[k];
    ary[k] = ary[n];
    ary[n] = tmp;
}

より厳密で簡単な方法

「Coding Horror: Shuffling」によると、上記の方法には2つの問題があるということです。1つは、Randomクラスが生成する配列が予測可能であり、安全ではないという点で、もう1つは、複雑であるという点です。これらの点を解消した方法として、OrderByメソッドで並び替え、Randomの代わりにGuidを使う方法が紹介されています。なお、OrderByメソッドは.NET Framework 3.5以降で使用でき、参照設定に「System.Core.dll」を追加する必要があります。OrderByメソッドについては、「配列やコレクション内の要素を並び替える」でも説明しています。

VB.NET
コードを隠すコードを選択
'Imports System.Linq
'がソースファイルの一番上に書かれているものとする

'シャッフルする配列 
Dim ary As Integer() = New Integer() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

'シャッフルする 
Dim ary2 As Integer() = ary.OrderBy(Function(i) Guid.NewGuid()).ToArray()
C#
コードを隠すコードを選択
//using System.Linq;
//がソースファイルの一番上に書かれているものとする

//シャッフルする配列
int[] ary = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

//シャッフルする
int[] ary2 = ary.OrderBy(i => Guid.NewGuid()).ToArray();
  • 履歴:
  • 2013/8/18 リンクの間違いを修正。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • 「???を参照に追加します」の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。