Randomize a List
Randomize a List
Randomize a List
Re: Randomize a List
Shuffle any `(I)List` with an extension method based on the [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle):
```
private static Random rng = new Random();
public static void Shuffle(this IList 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;
}
}
```
Usage:
```
List products = GetProducts();
products.Shuffle();
```
The code above uses the much criticised `System.Random` method to select swap candidates. It's fast but not as random as it should be. If you need a better quality of randomness in your shuffles, use the random number generator in `System.Security.Cryptography` like so:
```
using System.Security.Cryptography;
...
public static void Shuffle(this IList 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;
}
}
```
A simple comparison is available [at this blog](https://web.archive.org/web/20150801085341/http://blog.thijssen.ch/2010/02/when-random-is-too-consistent.html) (WayBack Machine).
Edit: Since writing this answer a couple years back, many people have commented or written to me, to point out the big silly flaw in my comparison. They are of course right. There's nothing wrong with `System.Random` if it's used in the way it was intended. In my first example above, I instantiate the `rng` variable inside of the `Shuffle` method, which is asking for trouble if the method is going to be called repeatedly. Below is a fixed, full example based on a really useful comment received today from @weston here on SO.
Program.cs:
```
using System;
using Sy
*(Réponse tronquée)*
```
private static Random rng = new Random();
public static void Shuffle(this IList 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;
}
}
```
Usage:
```
List products = GetProducts();
products.Shuffle();
```
The code above uses the much criticised `System.Random` method to select swap candidates. It's fast but not as random as it should be. If you need a better quality of randomness in your shuffles, use the random number generator in `System.Security.Cryptography` like so:
```
using System.Security.Cryptography;
...
public static void Shuffle(this IList 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;
}
}
```
A simple comparison is available [at this blog](https://web.archive.org/web/20150801085341/http://blog.thijssen.ch/2010/02/when-random-is-too-consistent.html) (WayBack Machine).
Edit: Since writing this answer a couple years back, many people have commented or written to me, to point out the big silly flaw in my comparison. They are of course right. There's nothing wrong with `System.Random` if it's used in the way it was intended. In my first example above, I instantiate the `rng` variable inside of the `Shuffle` method, which is asking for trouble if the method is going to be called repeatedly. Below is a fixed, full example based on a really useful comment received today from @weston here on SO.
Program.cs:
```
using System;
using Sy
*(Réponse tronquée)*