[解決済み] リスト<T>をランダム化する
2022-03-16 12:05:16
質問
C#で一般的なリストの順序をランダムにする最良の方法は何ですか?私は、有限の75個の数字のリストを持っていて、抽選のようなアプリケーションのために、ランダムな順序を割り当てたいと思っています。
どのように解決するのですか?
任意のシャッフル
(I)List
をベースにした拡張メソッドで
フィッシャーイェーツシャッフル
:
private static Random rng = new Random();
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
使用方法
List<Product> products = GetProducts();
products.Shuffle();
上記のコードでは、スワップ候補を選択するために、批判されている System.Random メソッドを使用しています。これは高速ですが、必要なほどランダムではありません。より質の高いランダム性が必要な場合は、System.Security.Cryptography の乱数発生器をこのように使用します。
using System.Security.Cryptography;
...
public static void Shuffle<T>(this IList<T> list)
{
RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
int n = list.Count;
while (n > 1)
{
byte[] box = new byte[1];
do provider.GetBytes(box);
while (!(box[0] < n * (Byte.MaxValue / n)));
int k = (box[0] % n);
n--;
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
簡単な比較は可能です このブログで (WayBack Machine)。
編集部:数年前にこの回答を書いてから、多くの人がコメントや手紙をくれて、私の比較の大きな愚かな欠点を指摘してくれました。もちろん、その通りです。System.Randomが意図されたとおりに使われるのであれば、何も問題はありません。上の最初の例では、Shuffle メソッドの中で変数 rng をインスタンス化していますが、このメソッドが繰り返し呼ばれることになるなら、これはトラブルのもとです。以下は、今日SOの@westonから受け取ったとても有用なコメントに基づいて、修正した完全な例です。
Program.cs:
using System;
using System.Collections.Generic;
using System.Threading;
namespace SimpleLottery
{
class Program
{
private static void Main(string[] args)
{
var numbers = new List<int>(Enumerable.Range(1, 75));
numbers.Shuffle();
Console.WriteLine("The winning numbers are: {0}", string.Join(", ", numbers.GetRange(0, 5)));
}
}
public static class ThreadSafeRandom
{
[ThreadStatic] private static Random Local;
public static Random ThisThreadsRandom
{
get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
}
}
static class MyExtensions
{
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
}
関連
-
[解決済み】「The breakpoint will not currently be hit」を改善するには?このドキュメントにはシンボルが読み込まれていません。" という警告はどうすれば改善されますか?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] 特定のプロパティに対するLINQのDistinct()
-
[解決済み] LINQのGroup by
-
[解決済み] .NETでapp.configやweb.configから設定を読み込む
-
[解決済み] LINQで.Firstと.FirstOrDefaultを使用するタイミングは?
-
[解決済み] 汎用クラスやメソッドのメンバからTの型を取得する方法
-
[解決済み] List<T> OrderBy Alphabetical Order(アルファベット順)
-
[解決済み】大文字・小文字を区別しない「Contains(string)
-
[解決済み】IEnumerable vs List - What to Use? どのように動作するのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「未割り当てのローカル変数を使用」とはどういう意味ですか?
-
[解決済み】指定されたキャストが有効でない?
-
[解決済み] メンバー '<メンバー名>' にインスタンス参照でアクセスできない
-
[解決済み】文字列が有効な DateTime " format dd/MM/yyyy " として認識されなかった。
-
[解決済み】ソケットのアドレス(プロトコル/ネットワークアドレス/ポート)は、通常1つしか使用できない?
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み】ファイルへの読み書きの際に共有違反のIOExceptionが発生する C#
-
[解決済み] 2つのリストを結合する
-
[解決済み】2年前のMSDateを把握する【クローズド
-
[解決済み】別のスレッドがこのオブジェクトを所有しているため、呼び出し側のスレッドはこのオブジェクトにアクセスできない