Randomize a List≪T≫

Randomize a ListT

Shuffle any (I)List with an extension method based on the Fisher-Yates shuffle:

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;
}
}

Usage:

List<Product> 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<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;
}
}

A simple comparison is available at this blog (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 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;
}
}
}
}

Simple way to randomly shuffle list

Try this (based on Fisher–Yates shuffle algorithm)

public static void ShuffleMe<T>(this IList<T> list)  
{
Random random = new Random();
int n = list.Count;

for(int i= list.Count - 1; i > 1; i--)
{
int rnd = random.Next(i + 1);

T value = list[rnd];
list[rnd] = list[i];
list[i] = value;
}
}

List<Color> colors = new List<Color> ();
colors.Add(Color.Black);
colors.Add(Color.White);
colors.Add(Color.Red);

colors.ShuffleMe();

shuffle (rearrange randomly) a Liststring

List<Foo> source = ...
var rnd = new Random();
var result = source.OrderBy(item => rnd.Next());

Obviously if you want real randomness instead of pseudo-random number generator you could use RNGCryptoServiceProvider instead of Random.

Randomize a list but with range

It's very easy to adapt a standard random shuffle algorithm to accept a starting index and a count:

public static void Shuffle<T>(IList<T> array, Random rng, int first, int count)
{
for (int n = count; n > 1;)
{
int k = rng.Next(n);
--n;
T temp = array[n+first];
array[n + first] = array[k + first];
array[k + first] = temp;
}
}

Then if you want to shuffle all but the first and the last items:

Shuffle(items, new Random(), 1, items.Count-2);

Randomly shuffle a List

I think all you want is this, it's a simple way to do it;

Random rand = new Random();
var models = garage.OrderBy(c => rand.Next()).Select(c => c.Model).ToList();

//Model is assuming that's the name of your property

Note : Random(), ironically, isn't actually very random but fine for a quick simple solution. There are better algorithms out there to do this, here's one to look at;

http://en.wikipedia.org/wiki/Fisher-Yates_shuffle

Randomize Liststring without duplicates

You can shuffle your List using Fisher–Yates algorithm in O(n); once your iterator equals n, perform a second shuffle and so on.

The pseudocode for it, as presented in wikipedia, is :

To shuffle an array a of n elements (indices 0..n-1):
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]

You could even write an extension method for that, something like :

    public static Random rand = new Random();

public static List<T> Shuffle<T>(this List<T> original)
{
List<T> lst = new List<T>(original);
for (int i = lst.Count - 1; i >= 1; i--)
{
int j = rand.Next(0, i + 1);
T tmp = lst[j];
lst[j] = lst[i];
lst[i] = tmp;
}
return lst;
}

so that you could generate your shuffled list with

var shuffled = notizen.Shuffle();

How do I shuffle a list?

Use the Fisher-Yates shuffle algorithm:

using System.Collections.Generic;

namespace System
{
extension Random
{
public virtual void Shuffle<T>(List<T> list)
{
for (let i = list.Count - 1; i > 0; i--)
{
let j = Next(0, i + 1);
let tmp = list[j];
list[j] = list[i];
list[i] = tmp;
}
}
}
}

Select N random elements from a ListT in C#

Iterate through and for each element make the probability of selection = (number needed)/(number left)

So if you had 40 items, the first would have a 5/40 chance of being selected. If it is, the next has a 4/39 chance, otherwise it has a 5/39 chance. By the time you get to the end you will have your 5 items, and often you'll have all of them before that.

This technique is called selection sampling, a special case of Reservoir Sampling. It's similar in performance to shuffling the input, but of course allows the sample to be generated without modifying the original data.

Shuffling a list of objects

random.shuffle should work. Here's an example, where the objects are lists:

from random import shuffle

x = [[i] for i in range(10)]
shuffle(x)
print(x)

# print(x) gives [[9], [2], [7], [0], [4], [5], [3], [1], [8], [6]]

Note that shuffle works in place, and returns None.

More generally in Python, mutable objects can be passed into functions, and when a function mutates those objects, the standard is to return None (rather than, say, the mutated object).

Randomize list with seed

Depending on how "consistent" you need the generated series to be, you could use string.GetHashCode:

string arbitrarySeed = "someValue";
System.Random random = new System.Random(arbitrarySeed.GetHashCode());
List<object> randomizedOptions = items?.OrderBy(o => random.Next()).ToList();

GetHashCode is not guaranteed to be consistent across .NET versions or implementations (e.g. Linux, Windows, macOS) but if you need localized consistency it may work for you.

Also note that BitConverter.ToInt32 will only take 4 bytes of the array you pass in, so "someValue" and "someValue2" would give you the same seed value.



Related Topics



Leave a reply



Submit