I have read an article about various shuffle algorithms over at Coding Horror. I have seen that somewhere people have done this to shuffle a list:
var r = ne
I found Jon Skeet's answer to be entirely satisfactory, but my client's robo-scanner will report any instance of Random
as a security flaw. So I swapped it out for System.Security.Cryptography.RNGCryptoServiceProvider
. As a bonus, it fixes that thread-safety issue that was mentioned. On the other hand, RNGCryptoServiceProvider
has been measured as 300x slower than using Random
.
Usage:
using (var rng = new RNGCryptoServiceProvider())
{
var data = new byte[4];
yourCollection = yourCollection.Shuffle(rng, data);
}
Method:
///
/// Shuffles the elements of a sequence randomly.
///
/// A sequence of values to shuffle.
/// An instance of a random number generator.
/// A placeholder to generate random bytes into.
/// A sequence whose elements are shuffled randomly.
public static IEnumerable Shuffle(this IEnumerable source, RNGCryptoServiceProvider rng, byte[] data)
{
var elements = source.ToArray();
for (int i = elements.Length - 1; i >= 0; i--)
{
rng.GetBytes(data);
var swapIndex = BitConverter.ToUInt32(data, 0) % (i + 1);
yield return elements[swapIndex];
elements[swapIndex] = elements[i];
}
}