Dies ist meine bevorzugte Methode zum Mischen, wenn es erwünscht ist, das Original nicht zu verändern. Es handelt sich um eine Variante des Fisher-Yates "Inside-Out" Algorithmus, der auf jeder zählbaren Sequenz funktioniert (die Länge von source
muss nicht von Anfang an bekannt sein).
public static IList NextList(this Random r, IEnumerable source)
{
var list = new List();
foreach (var item in source)
{
var i = r.Next(list.Count + 1);
if (i == list.Count)
{
list.Add(item);
}
else
{
var temp = list[i];
list[i] = item;
list.Add(temp);
}
}
return list;
}
Dieser Algorithmus kann auch umgesetzt werden, indem man einen Bereich von 0
bis Länge - 1
zuweist und die Indizes zufällig erschöpft, indem man den zufällig gewählten Index mit dem letzten Index vertauscht, bis alle Indizes genau einmal gewählt wurden. Der obige Code erreicht genau dasselbe, braucht aber keine zusätzliche Zuweisung. Was ziemlich praktisch ist.
In Bezug auf die Random
Klasse handelt es sich um einen allgemeinen Zweck Zufallszahlengenerator (wenn ich eine Lotterie führen würde, würde ich erwägen, etwas anderes zu verwenden). Standardmäßig verwendet er auch einen auf der Zeit basierenden Startwert. Eine kleine Erleichterung des Problems besteht darin, die Random
Klasse mit dem RNGCryptoServiceProvider
zu starten oder Sie könnten den RNGCryptoServiceProvider
in einer ähnlichen Methode wie dieser (siehe unten) verwenden, um gleichmäßig gewählte zufällige Double-Gleitkommazahlen zu generieren, doch für eine Lotterie ist es notwendig, das Konzept von Zufälligkeit und die Natur der Zufallsquellen zu verstehen.
var bytes = new byte[8];
_secureRng.GetBytes(bytes);
var v = BitConverter.ToUInt64(bytes, 0);
return (double)v / ((double)ulong.MaxValue + 1);
Der Zweck, eine zufällige Double (zwischen 0 und 1 exklusiv) zu generieren, besteht darin, sie zu einer ganzzahligen Lösung zu skalieren. Wenn Sie etwas aus einer Liste basierend auf einem zufälligen Double x
auswählen müssen, das immer 0 <= x && x < 1
ist, ist es einfach.
return list[(int)(x * list.Count)];
Viel Spaß!
4 Stimmen
Es gibt ein offenes Problem, um diese Funktionalität in .NET zu integrieren: github.com/dotnet/corefx/issues/461
7 Stimmen
Du könntest an diesem NuGet-Paket interessiert sein, das Erweiterungsmethoden für das Mischen von IList und IEnumerable mithilfe des unten erwähnten Fisher-Yates-Algorithmus enthält
0 Stimmen
Es gibt auch verwandte Wählen Sie N zufällige Elemente aus einer Liste und Diskussion zu Shuffle mit OrderBy vs. Fisher-Yates.