What is the best way to randomize the order of a generic list in C#? I've got a finite set of 75 numbers in a list I would like to assign a random order to, in order to draw them for a lottery type application.
-
6There is an open issue to integrate this functionality to .NET: https://github.com/dotnet/corefx/issues/461 – Natan Mar 07 '15 at 10:19
-
7You may be interested in [this NuGet package](https://github.com/madelson/MedallionUtilities/tree/master/MedallionRandom#shuffling), which contains extension methods for shuffling IList
and IEnumerable – ChaseMedallion May 07 '16 at 14:44using the Fisher-Yates algorithm mentioned below -
There is also related [Select N random elements from a List
](http://stackoverflow.com/questions/48087/select-n-random-elements-from-a-listt-in-c-sharp) and [Shuffle with OrderBy vs. Fisher-Yates](http://stackoverflow.com/questions/1287567/is-using-random-and-orderby-a-good-shuffle-algorithm) discussion. – Alexei Levenkov Feb 05 '17 at 07:51 -
1Shuffling a `T[]` might at least be coming to .Net 8?: [Random.Shuffle](https://learn.microsoft.com/en-us/dotnet/api/system.random.shuffle?view=net-8.0) – teichert Mar 24 '23 at 23:39
31 Answers
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;
}
}
}
}
-
2Note that the performance of this is drastically lower on LinkedLists vs ArrayLists. Always be sure to send it a O(1) performance indexable array. – TheSoftwareJedi Jan 12 '10 at 20:08
-
@Jedi if that were a significant problem, it would perhaps be beneficial to create a secondary storage list or array, do the shuffling there, and replace the contents of the list with that. – corsiKa Mar 21 '11 at 20:52
-
37What if list.Count is > Byte.MaxValue? If n = 1000, then 255 / 1000 = 0, so the do loop will be an infinite loop since box[0] < 0 is always false. – AndrewS Jun 07 '11 at 10:47
-
19I would like to point out, that the comparison is flawed. Using
new Random()
in a loop is the problem, not the randomness ofRandom
[Explanation](http://stackoverflow.com/questions/3053807/random-number-in-a-loop/3053811#3053811) – Sven Sep 29 '11 at 13:43 -
9It is a good idea to pass an instance of Random to the Shuffle method rather than create it inside as if you are calling Shuffle lots of times in quick succession (e.g. shuffling lots of short lists), the lists will all be shuffled in the same way (e.g. first item always gets moved to position 3). – Mark Heath Feb 07 '12 at 22:43
-
2You comparison article is missing a bit the point. `System.Random` is not as bad as you show. `new Random()` is [using a time-dependent default seed value](http://msdn.microsoft.com/en-us/library/h343ddh9.aspx) which is why there is no randomization at all in your test. For a true reason, see http://boallen.com/random-numbers.html but again that's a bit OS-dependent so `System.Random` may perform better, or not. – Wernight Sep 11 '12 at 16:58
-
8Just making `Random rng = new Random();` a `static` would solve the problem in the comparison post. As each subsequent call would follow on from the previous calls last random result. – weston Nov 28 '12 at 13:58
-
Don't forget to dispose the random provider after you finish using it. – Andrei Micu Dec 23 '12 at 11:21
-
Making the Random static is a dangerous idea because now the method isn't thread-safe. Also what about AndrewS's point in the "secure" version? – Mark Sowul May 08 '13 at 03:21
-
1I'll be honest @MarkSowul and tell you that I don't know much about the dangers of statics or thread safety. Will I get eaten by lions, stampeded by ponies or what kind of dangers will I face? I also don't know the answer or claim to understand the question posed by AndrewS. – grenade May 08 '13 at 12:31
-
3If two different threads use the version with a shared RNG at the same time, the RNG is apt to corrupt its state because it's not thread-safe (http://stackoverflow.com/a/11109361/155892). – Mark Sowul May 08 '13 at 14:36
-
6#2, it's not clear that the version with the Crypto generator works because the max range of a byte is 255, so any list larger than that will not shuffle correctly. – Mark Sowul May 08 '13 at 14:37
-
1I agree that my idea was not threadsafe, and because you weren't clear on threadsafety issues, I have added `ThreadSafeRandom` class based on Mark Sowuls answer myself, hope that's cool! – weston May 10 '13 at 08:53
-
If you would use `ThreadSafeRandom` in ASP.NET I believe you would generate many many instances of `Local`. I wouldn't even think they'd be garbage collected either until AppDomain tear down. – Chris Marisic Sep 17 '14 at 15:41
-
why do provider.GetBytes(box); while (!(box[0] < n * (Byte.MaxValue / n))); int k = (box[0] % n); instead of do provider.GetBytes(box); while (box[0] >= n); int k = box[0]; – roim Oct 09 '14 at 14:51
-
Say one wants to provide a copy of the shuffled list while keeping the original intact. How would one go about accomplishing that? – Will Dec 21 '14 at 21:56
-
Even though there is a new-and-improved thread-safe version, you still have the same issue if a single thread calls Shuffle in a tight loop. I edited the original example to prevent people that just copy-and-paste the solution without reading the discussion from running into the tight loop issue. – Eric J. Jul 16 '15 at 20:38
-
1@Will: Make a copy before you shuffle, and shuffle that copy. The Linq extension method .ToList() will do nicely for that, but note if you have a list of a reference type, both will reference the original object, e.g. if you have `List
a = LoadSomehow(); List – Eric J. Jul 16 '15 at 20:38b = a.ToList(); b.Shuffle ();` the two lists will have the same Person instances, but in different orders. -
5The number of bits of entropy in your PRNG must be carefully examined. For example, to shuffle a 52-card deck and be able to get every possible shuffled deck, and do that with equal probability, **you need a PRNG with at least a 226-bit seed!** Please don't use the methods in this answer for shuffling things when equal probability of all possible outcomes is needed, unless you do the proper computer science to ensure it works correctly. – ErikE Oct 14 '15 at 20:10
-
1
-
I would make a small change to this, namely having it copy the incoming list, shuffle this new list, and return it. Then you can do things like `var shuffledList = originalList.Shuffle();` – Dagrooms May 31 '16 at 16:13
-
Unluckily I can't use the thread-safe version, since I'm using VB.NET and there's no `unchecked`, nor a valid alternative. – Marco Sulla Jun 24 '16 at 16:20
-
What is the point of the condition for the do while loop? Why not just grab a byte and then do the % list.Count? – Phoenix Dec 05 '16 at 21:39
-
To achieve good entropy with better performance, without the silly `while`-loop or the 255-element limit, you can pre-calculate the number of random bytes required to run the algorithm to completion (`sizeof(int) * (list.Count - 1)`, or of `long` if working on raw arrays) and fill a byte-array with a single call to `GetBytes()`. Then wrap that byte-array in a `MemoryStream` using the wrapping constructor (practically free) and read random integers from it using a `BinaryReader`. Do not forget to dispose disposable instances! (You can support larger lists by making a circular buffer.) – Xharlie Jan 04 '17 at 14:24
-
why do you need the Random instance to be thread safe? as far as I can see your code is doing all the calculation in 1 thread – Daniel Perez Dec 13 '17 at 10:57
-
1I think your RNGCryptoServiceProvider implementation will produce an uncertain randomness when the list count is beyond 255. It also has a tendency for an infinite loop by the list count. A rework below: int RandomInteger() { cryptoServiceProvider.GetBytes(randomIntegerBuffer); return BitConverter.ToInt32(randomIntegerBuffer, 0); } var result = from item in source let record = new { Item = item, RandomKey = RandomInteger() } orderby record.RandomKey select record.Item; – William Jan 15 '19 at 15:56
-
I had to change the array count as it clipped missing array index 0 int listSize = list.Count; while (listSize > 0) //while list greater than 0 of course i'm a noob - so I might also be doing it weirdly :P – StackBuddy Mar 15 '19 at 11:37
-
1@William I faced exactly this problem, just trying to shuffle 1000 elements leads to infinite looping. DO NOT USE the first version of the method in the answer. – Vitalii Isaenko Jul 16 '19 at 10:29
-
I am just curious. Is it really necessary to subtract the `1` from `n` at first and then add it back? Also, the postcrement operators create additional instance, so it is better performance wise to use the precrement operator here. All that being said I would change the two lines to the following: first `int k = ThreadSafeRandom.ThisThreadsRandom.Next(n);` second `--n`. But anyway I am grateful to you for providing this algorithm. – qqqqqqq Mar 07 '20 at 18:44
-
@Xharlie I know this is an old post, but I'm interested in your proposed implementation for using the random byte array... do you have a sample somewhere that I could learn from? Thank you. – Chris Keller May 09 '21 at 00:15
-
1I would write the while loop as a for loop: `for (int n = list.Count-1; n>0; --n)`, but maybe that's just the C programmer in me. – JHBonarius Nov 04 '21 at 09:32
-
I've packaged this solution with a thread-safe random generator at https://nuget.org/packages/ListShuffle / https://github.com/MarkCiliaVincenti/ListShuffle – Mark Cilia Vincenti Mar 13 '22 at 16:57
-
I had found the shuffle method(using RNGCryptoServiceProvider) might make program hang. Probably caused by the items in List are more than 256. :( – firestoke Apr 15 '22 at 03:45
If we only need to shuffle items in a completely random order (just to mix the items in a list), I prefer this simple yet effective code that orders items by guid...
var shuffledcards = cards.OrderBy(a => Guid.NewGuid()).ToList();
As people have pointed out in the comments, GUIDs are not guaranteed to be random, so we should be using a real random number generator instead:
private static Random rng = new Random();
...
var shuffledcards = cards.OrderBy(a => rng.Next()).ToList();

- 167,459
- 57
- 363
- 519

- 5,597
- 1
- 14
- 2
-
1This is leveraging a [Linq](http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx) method to reorder the list. [NewGuid](http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx) creates a random [Guid](http://msdn.microsoft.com/en-us/library/system.guid.aspx) (a 16 byte value). [OrderBy](http://msdn.microsoft.com/en-us/library/bb534966.aspx) uses the function provided to assign a comparable object to each card, and then returns a new collection ordered by the Guids. Since Guids are so long, the chances of a collision (same Guid for two different objects) are very small. – Christopher Stevenson Mar 28 '13 at 16:06
-
50GUIDs are meant to be unique not random. Part of it is machine-based and another part time-based and only a small portion is random. http://blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx – Despertar May 05 '13 at 07:00
-
129This is a nice elegant solution. If you want something other than a guid to generate randomness, just order by something else. Eg: `var shuffledcards = cards.OrderBy(a => rng.Next());` https://compilr.com/grenade/sandbox/Program.cs – grenade May 27 '13 at 10:54
-
Note that only certain types of GUIDs are machine-based or time-based. GUIDs created in this manner (Guid.NewGuid()) are neither machine-based nor time-based (i.e. Sequential GUID). This is a good way to shuffle a list. – Doug Jun 12 '13 at 04:16
-
Another thing to watch out for is that the lambda could be called multiple times, in which case it will return different values for the same item. That might slow the sorting down. I don't know if this is the case for the default implementation of OrderBy though. In any case I'd recommend using the Fisher-Yates shuffle. – Herman Jul 24 '13 at 10:26
-
28Please no. This is wrong. "ordering by random" is totally NOT a shuffle: you introduce a bias and, worse, you risk to go in infinite loops – Vito De Tullio Aug 16 '13 at 10:07
-
95@VitoDeTullio: You are misremembering. You risk infinite loops when you provide a random *comparison function*; a comparison function is required to produce a consistent *total order*. A random *key* is fine. This suggestion is wrong because *guids are not guaranteed to be random*, not because the technique of sorting by a random key is wrong. – Eric Lippert Sep 13 '13 at 21:30
-
31@Doug: `NewGuid` only guarantees that it gives you a unique GUID. It makes no guarantees about randomness. If you're using a GUID for a purpose other than creating a *unique* value, you're doing it wrong. – Eric Lippert Sep 13 '13 at 21:31
-
1@Eric - You're correct, this probably isn't the most random way to shuffle a list. For those interested: http://stackoverflow.com/questions/2621563/how-random-is-system-guid-newguid-take-two – Doug Dec 13 '13 at 16:12
-
3Is there any guarantee that the key function is only called once per element? (I didn't find any mention of it in the documentation.) If so, this is quite elegant. Otherwise, this code indeed risks endless loops (or increased runtime) and other hard-to-predict inconsistencies. – Roland Illig Aug 05 '16 at 20:19
-
1
-
@RolandIllig (1) `OrderBy(x => x.Id)` (2) `Orderby(x => 5)` (3) `OrderBy(x => rng.Next())` None of these create an endless loop. The **value** selected in the OrderBy does not influence the processing of the elements. Every item in the list will have its value retrieved exactly once. Note that you would be correct if e.g. OrderBy was a bubble sort that did not cache the values; but that is not the case here. – Flater May 28 '18 at 06:03
-
1@Flater "Every item in the list will have its value retrieved exactly once" — says who? – Roland Illig May 28 '18 at 18:09
-
@RolandIllig `Enumerable.Range(0,10).OrderBy(x => GetRandomNumberAndLogMessageToConsole());` I assume the name is descriptive enough. – Flater May 28 '18 at 19:34
-
4This is a great answer, but I want to add a warning to people using it: it's not a good idea if you've got really large lists. The O(n) notation for .OrderBy(RandomFunc) is n*log(n), not n. For 1-1000 entries, this isn't a big deal. For a million entries, it'll be ~100 times slower; for a billion entries, it'll be ~1000 times slower. – Kevin Jun 14 '18 at 19:32
-
1This kind of "randomness" introduced a bug in my application that took 4 days to find (lists were consistently not-random-at-all). Just don't do it. – mafu Jun 26 '20 at 14:21
-
1Fantastic how this keeps evolving. If you look at the source code in dotnet core, `Guid.NewGuid()` does as people have said draw from an interop call to Windows... if you're on Windows. However, every other OS uses `RNGCryptoServiceProvider ` which most certainly *does* derive from random bytes. – Jeff Putz Oct 17 '20 at 22:20
-
1There is no guarantee that I can find that states the key is extracted exactly once for each element. Thus, the BCL can implement `OrderBy` in a way that this solution is a random comparison function. – Stephen Cleary Jan 07 '22 at 16:11
-
@JeffPutz NewGuid is guarranteed to have strong entropy on all platforms as documented - https://learn.microsoft.com/en-us/dotnet/api/system.guid.newguid?view=net-7.0 - the implementation is platform dependent, but on all platforms the specs promise cryptographically strong entropy. – Eamon Nerbonne May 30 '23 at 10:46
-
@EamonNerbonne it doesn't matter. There's no universe where these aren't "random enough" for any use. It's just something us nerds like to argue about, even two years later. :) – Jeff Putz May 30 '23 at 14:04
-
@JeffPutz prior to .net 6, it was possible for entropy to be from a non-random enough source on non-windows platforms that conceivably the list would have have been randomly shuffled. Having predictable, non-random distribution is a serious concern for some usages (e.g. some stochastic algorithms and security), so it's nice to know that that's no longer a concern even for those likely very small niches. – Eamon Nerbonne Jun 06 '23 at 09:57
I'm bit surprised by all the clunky versions of this simple algorithm here. Fisher-Yates (or Knuth shuffle) is bit tricky but very compact. Why is it tricky? Because your need to pay attention to whether your random number generator r(a,b)
returns value where b
is inclusive or exclusive. I've also edited Wikipedia description so people don't blindly follow pseudocode there and create hard to detect bugs. For .Net, Random.Next(a,b)
returns number exclusive of b
so without further ado, here's how it can be implemented in C#/.Net:
public static void Shuffle<T>(this IList<T> list, Random rnd)
{
for(var i=list.Count; i > 0; i--)
list.Swap(0, rnd.Next(0, i));
}
public static void Swap<T>(this IList<T> list, int i, int j)
{
var temp = list[i];
list[i] = list[j];
list[j] = temp;
}

- 63,284
- 17
- 238
- 185
-
7This code does not work as expected. The last number is always `0` or `list.Count-1`. – Oneiros Jan 03 '20 at 17:52
-
3@ShitalShah The current code in your answer doesn't give correct results, because it's not a correct Fisher-Yates shuffle. It should be fixed, as well as the code in the link. – Trisibo Jul 13 '20 at 18:37
-
6This code is broken. If you used a list of strings for 3 letters, "A", "B", and "C", CBA, and BCA would literally never occur using this function, because of this line: `list.Swap(0, rnd.Next(0, i));` switching it to the following fixes it and makes it a working, non-biased pseudo-random function: `list.Swap(i-1, rnd.Next(0, i));` – Garrison Becker Aug 10 '20 at 12:21
-
5OP: "Fischer-Yates is a bit tricky." Proceeds to make one of the many common implementation mistakes. – D0SBoots Feb 13 '22 at 06:10
Extension method for IEnumerable:
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
Random rnd = new Random();
return source.OrderBy<T, int>((item) => rnd.Next());
}
-
11There are two significant problems with this algorithm: -- `OrderBy` uses a QuickSort variant to sort the items by their (ostensibly random) keys. QuickSort performance is _O(N log N)_; in contrast, a Fisher-Yates shuffle is _O(N)_. For a collection of 75 elements, this may not be a big deal, but the difference will become pronounced for larger collections. – John Beyer Jun 26 '13 at 16:47
-
13... -- `Random.Next()` may produce a reasonably pseudo-random distribution of values, but it does _not_ guarantee that the values will be unique. The probability of duplicate keys grows (non-linearly) with _N_ until it reaches certainty when _N_ reaches 2^32+1. The `OrderBy` QuickSort is a _stable_ sort; thus, if multiple elements happen to get assigned the same pseudo-random index value, then their order in the output sequence will be the _same_ as in the input sequence; thus, a bias is introduced into the "shuffle". – John Beyer Jun 26 '13 at 17:06
-
37@JohnBeyer: There are far, far greater problems than that source of bias. There are only four billion possible seeds to Random, which is far, far less than the number of possible shuffles of a moderately sized set. Only a tiny fraction of the possible shuffles can be generated. That bias dwarfs the bias due to accidental collisions. – Eric Lippert Sep 13 '13 at 21:33
-
Another problem with Random is that, when two (or more) instances of Random get created shortly after one another, they might have the same seed (seed is taken from system clock and the clock resolution might be too big to register a change). – jahu May 14 '21 at 10:16
Idea is get anonymous object with item and random order and then reorder items by this order and return value:
var result = items.Select(x => new { value = x, order = rnd.Next() })
.OrderBy(x => x.order).Select(x => x.value).ToList()

- 37,241
- 25
- 195
- 267

- 445
- 4
- 7
public static List<T> Randomize<T>(List<T> list)
{
List<T> randomizedList = new List<T>();
Random rnd = new Random();
while (list.Count > 0)
{
int index = rnd.Next(0, list.Count); //pick a random item from the master list
randomizedList.Add(list[index]); //place it at the end of the randomized list
list.RemoveAt(index);
}
return randomizedList;
}

- 25,378
- 33
- 125
- 153
EDIT
The RemoveAt
is a weakness in my previous version. This solution overcomes that.
public static IEnumerable<T> Shuffle<T>(
this IEnumerable<T> source,
Random generator = null)
{
if (generator == null)
{
generator = new Random();
}
var elements = source.ToArray();
for (var i = elements.Length - 1; i >= 0; i--)
{
var swapIndex = generator.Next(i + 1);
yield return elements[swapIndex];
elements[swapIndex] = elements[i];
}
}
Note the optional Random generator
, if the base framework implementation of Random
is not thread-safe or cryptographically strong enough for your needs, you can inject your implementation into the operation.
Here's an idea, extend IList in a (hopefully) efficient way.
public static IEnumerable<T> Shuffle<T>(this IList<T> list)
{
var choices = Enumerable.Range(0, list.Count).ToList();
var rng = new Random();
for(int n = choices.Count; n > 1; n--)
{
int k = rng.Next(n);
yield return list[choices[k]];
choices.RemoveAt(k);
}
yield return list[choices[0]];
}
If you don't mind using two Lists
, then this is probably the easiest way to do it, but probably not the most efficient or unpredictable one:
List<int> xList = new List<int>() { 1, 2, 3, 4, 5 };
List<int> deck = new List<int>();
foreach (int xInt in xList)
deck.Insert(random.Next(0, deck.Count + 1), xInt);
This is my preferred method of a shuffle when it's desirable to not modify the original. It's a variant of the Fisher–Yates "inside-out" algorithm that works on any enumerable sequence (the length of source
does not need to be known from start).
public static IList<T> NextList<T>(this Random r, IEnumerable<T> source)
{
var list = new List<T>();
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;
}
This algorithm can also be implemented by allocating a range from 0
to length - 1
and randomly exhausting the indices by swapping the randomly chosen index with the last index until all indices have been chosen exactly once. This above code accomplishes the exact same thing but without the additional allocation. Which is pretty neat.
With regards to the Random
class it's a general purpose number generator (and If I was running a lottery I'd consider using something different). It also relies on a time based seed value by default. A small alleviation of the problem is to seed the Random
class with the RNGCryptoServiceProvider
or you could use the RNGCryptoServiceProvider
in a method similar to this (see below) to generate uniformly chosen random double floating point values but running a lottery pretty much requires understanding randomness and the nature of the randomness source.
var bytes = new byte[8];
_secureRng.GetBytes(bytes);
var v = BitConverter.ToUInt64(bytes, 0);
return (double)v / ((double)ulong.MaxValue + 1);
The point of generating a random double (between 0 and 1 exclusively) is to use to scale to an integer solution. If you need to pick something from a list based on a random double x
that's always going to be 0 <= x && x < 1
is straight forward.
return list[(int)(x * list.Count)];
Enjoy!

- 59,920
- 20
- 131
- 152
One can use the Shuffle extension methond from morelinq package, it works on IEnumerables
install-package morelinq
using MoreLinq;
...
var randomized = list.Shuffle();

- 329
- 1
- 4
- 9
You can achieve that be using this simple extension method
public static class IEnumerableExtensions
{
public static IEnumerable<t> Randomize<t>(this IEnumerable<t> target)
{
Random r = new Random();
return target.OrderBy(x=>(r.Next()));
}
}
and you can use it by doing the following
// use this on any collection that implements IEnumerable!
// List, Array, HashSet, Collection, etc
List<string> myList = new List<string> { "hello", "random", "world", "foo", "bar", "bat", "baz" };
foreach (string s in myList.Randomize())
{
Console.WriteLine(s);
}

- 7,148
- 1
- 25
- 18
Just wanted to suggest a variant using an IComparer<T>
and List.Sort()
:
public class RandomIntComparer : IComparer<int>
{
private readonly Random _random = new Random();
public int Compare(int x, int y)
{
return _random.Next(-1, 2);
}
}
Usage:
list.Sort(new RandomIntComparer());

- 1,631
- 2
- 18
- 23
I usually use:
var list = new List<T> ();
fillList (list);
var randomizedList = new List<T> ();
var rnd = new Random ();
while (list.Count != 0)
{
var index = rnd.Next (0, list.Count);
randomizedList.Add (list [index]);
list.RemoveAt (index);
}

- 26,396
- 5
- 54
- 57
If you have a fixed number (75), you could create an array with 75 elements, then enumerate your list, moving the elements to randomized positions in the array. You can generate the mapping of list number to array index using the Fisher-Yates shuffle.

- 3,993
- 6
- 35
- 39
You can make the Fisher-Yates shuffle more terse and expressive by using tuples for the swap.
private static readonly Random random = new Random();
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = random.Next(n + 1);
(list[k], list[n]) = (list[n], list[k]);
}
}

- 1,069
- 13
- 20
We can use an extension method for List and use a thread-safe random generator combination. I've packaged an improved version of this on NuGet with the source code available on GitHub. The NuGet version contains optional cryptographically-strong random.
Pre-.NET 6.0 version:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Shuffle<T>(this IList<T> list)
{
if (list == null) throw new ArgumentNullException(nameof(list));
int n = list.Count;
while (n > 1)
{
int k = ThreadSafeRandom.Instance.Next(n--);
(list[n], list[k]) = (list[k], list[n]);
}
}
internal class ThreadSafeRandom
{
public static Random Instance => _local.Value;
private static readonly Random _global = new Random();
private static readonly ThreadLocal<Random> _local = new ThreadLocal<Random>(() =>
{
int seed;
lock (_global)
{
seed = _global.Next();
}
return new Random(seed);
});
}
On .NET 6.0 or later:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Shuffle<T>(this IList<T> list)
{
ArgumentNullException.ThrowIfNull(list);
int n = list.Count;
while (n > 1)
{
int k = Random.Shared.Next(n--);
(list[n], list[k]) = (list[k], list[n]);
}
}
Install the library via NuGet for more features.

- 1,410
- 8
- 25
-
-
1Yes, @Dohab. Use the NuGet package I linked above. Basically you just call `myList.Shuffle();` and it's shuffled. There's also a `.CryptoStrongShuffle();` – Mark Cilia Vincenti Jun 30 '22 at 08:07
Implementation:
public static class ListExtensions
{
public static void Shuffle<T>(this IList<T> list, Random random)
{
for (var i = list.Count - 1; i > 0; i--)
{
int indexToSwap = random.Next(i + 1);
(list[indexToSwap], list[i]) = (list[i], list[indexToSwap]);
}
}
}
Example:
var random = new Random();
var array = new [] { 1, 2, 3 };
array.Shuffle(random);
foreach (var item in array) {
Console.WriteLine(item);
}

- 579
- 7
- 6
Starting in .NET 8 (still in preview), you can use Shuffle()
:
//Argument is Span<T> or T[]
Random.Shared.Shuffle(mySpan);
Or, for a cryptographically strong randomness:
//Argument is Span<T>
RandomNumberGenerator.Shuffle(mySpan);
For a list, you would have to create an array first (myList.ToArray()
) shuffle as above and then create a new list from the shuffled array

- 7,495
- 1
- 25
- 41
-
Or you can do: `var span = CollectionsMarshal.AsSpan(list);` to avoid converting to array. – Magnus Aug 07 '23 at 13:26
A simple modification of the accepted answer that returns a new list instead of working in-place, and accepts the more general IEnumerable<T>
as many other Linq methods do.
private static Random rng = new Random();
/// <summary>
/// Returns a new list where the elements are randomly shuffled.
/// Based on the Fisher-Yates shuffle, which has O(n) complexity.
/// </summary>
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> list) {
var source = list.ToList();
int n = source.Count;
var shuffled = new List<T>(n);
shuffled.AddRange(source);
while (n > 1) {
n--;
int k = rng.Next(n + 1);
T value = shuffled[k];
shuffled[k] = shuffled[n];
shuffled[n] = value;
}
return shuffled;
}

- 1,654
- 16
- 30
List<T> OriginalList = new List<T>();
List<T> TempList = new List<T>();
Random random = new Random();
int length = OriginalList.Count;
int TempIndex = 0;
while (length > 0) {
TempIndex = random.Next(0, length); // get random value between 0 and original length
TempList.Add(OriginalList[TempIndex]); // add to temp list
OriginalList.RemoveAt(TempIndex); // remove from original list
length = OriginalList.Count; // get new list <T> length.
}
OriginalList = new List<T>();
OriginalList = TempList; // copy all items from temp list to original list.

- 2,150
- 3
- 25
- 34

- 210
- 3
- 8
Here is an implementation of the Fisher-Yates shuffle that allows specification of the number of elements to return; hence, it is not necessary to first sort the whole collection before taking your desired number of elements.
The sequence of swapping elements is reversed from default; and proceeds from the first element to the last element, so that retrieving a subset of the collection yields the same (partial) sequence as shuffling the whole collection:
collection.TakeRandom(5).SequenceEqual(collection.Shuffle().Take(5)); // true
This algorithm is based on Durstenfeld's (modern) version of the Fisher-Yates shuffle on Wikipedia.
public static IList<T> TakeRandom<T>(this IEnumerable<T> collection, int count, Random random) => shuffle(collection, count, random);
public static IList<T> Shuffle<T>(this IEnumerable<T> collection, Random random) => shuffle(collection, null, random);
private static IList<T> shuffle<T>(IEnumerable<T> collection, int? take, Random random)
{
var a = collection.ToArray();
var n = a.Length;
if (take <= 0 || take > n) throw new ArgumentException("Invalid number of elements to return.");
var end = take ?? n;
for (int i = 0; i < end; i++)
{
var j = random.Next(i, n);
(a[i], a[j]) = (a[j], a[i]);
}
if (take.HasValue) return new ArraySegment<T>(a, 0, take.Value);
return a;
}

- 335
- 3
- 12
Beginning with .net 8.0
The new Random.Shuffle
and RandomNumberGenerator.Shuffle<T>(Span<T>)
methods let you randomize the order of a span of items.
int[] myNumbers = LoadNumbers();
Random.Shared.Shuffle(myNumbers);
// myNumbers are now shuffled.

- 5,052
- 5
- 34
- 44
Here's an efficient Shuffler that returns a byte array of shuffled values. It never shuffles more than is needed. It can be restarted from where it previously left off. My actual implementation (not shown) is a MEF component that allows a user specified replacement shuffler.
public byte[] Shuffle(byte[] array, int start, int count)
{
int n = array.Length - start;
byte[] shuffled = new byte[count];
for(int i = 0; i < count; i++, start++)
{
int k = UniformRandomGenerator.Next(n--) + start;
shuffled[i] = array[k];
array[k] = array[start];
array[start] = shuffled[i];
}
return shuffled;
}
`

- 8,420
- 10
- 51
- 68
I have found an interesting solution online.
Courtesy: https://improveandrepeat.com/2018/08/a-simple-way-to-shuffle-your-lists-in-c/
var shuffled = myList.OrderBy(x => Guid.NewGuid()).ToList();

- 2,033
- 2
- 18
- 39
-
This answer looks to duplicate https://stackoverflow.com/a/4262134/13893216. – Andrew McClement Jul 30 '23 at 19:33
Your question is how to randomize a list. This means:
- All unique combinations should be possible of happening
- All unique combinations should occur with the same distribution (AKA being non-biased).
A large number of the answers posted for this question do NOT satisfy the two requirements above for being "random".
Here's a compact, non-biased pseudo-random function following the Fisher-Yates shuffle method.
public static void Shuffle<T>(this IList<T> list, Random rnd)
{
for (var i = list.Count-1; i > 0; i--)
{
var randomIndex = rnd.Next(i + 1); //maxValue (i + 1) is EXCLUSIVE
list.Swap(i, randomIndex);
}
}
public static void Swap<T>(this IList<T> list, int indexA, int indexB)
{
var temp = list[indexA];
list[indexA] = list[indexB];
list[indexB] = temp;
}

- 32,158
- 14
- 82
- 96

- 481
- 3
- 12
Here's a thread-safe way to do this:
public static class EnumerableExtension
{
private static Random globalRng = new Random();
[ThreadStatic]
private static Random _rng;
private static Random rng
{
get
{
if (_rng == null)
{
int seed;
lock (globalRng)
{
seed = globalRng.Next();
}
_rng = new Random(seed);
}
return _rng;
}
}
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
{
return items.OrderBy (i => rng.Next());
}
}

- 2,843
- 20
- 25
public Deck(IEnumerable<Card> initialCards)
{
cards = new List<Card>(initialCards);
public void Shuffle()
}
{
List<Card> NewCards = new List<Card>();
while (cards.Count > 0)
{
int CardToMove = random.Next(cards.Count);
NewCards.Add(cards[CardToMove]);
cards.RemoveAt(CardToMove);
}
cards = NewCards;
}
public IEnumerable<string> GetCardNames()
{
string[] CardNames = new string[cards.Count];
for (int i = 0; i < cards.Count; i++)
CardNames[i] = cards[i].Name;
return CardNames;
}
Deck deck1;
Deck deck2;
Random random = new Random();
public Form1()
{
InitializeComponent();
ResetDeck(1);
ResetDeck(2);
RedrawDeck(1);
RedrawDeck(2);
}
private void ResetDeck(int deckNumber)
{
if (deckNumber == 1)
{
int numberOfCards = random.Next(1, 11);
deck1 = new Deck(new Card[] { });
for (int i = 0; i < numberOfCards; i++)
deck1.Add(new Card((Suits)random.Next(4),(Values)random.Next(1, 14)));
deck1.Sort();
}
else
deck2 = new Deck();
}
private void reset1_Click(object sender, EventArgs e) {
ResetDeck(1);
RedrawDeck(1);
}
private void shuffle1_Click(object sender, EventArgs e)
{
deck1.Shuffle();
RedrawDeck(1);
}
private void moveToDeck1_Click(object sender, EventArgs e)
{
if (listBox2.SelectedIndex >= 0)
if (deck2.Count > 0) {
deck1.Add(deck2.Deal(listBox2.SelectedIndex));
}
RedrawDeck(1);
RedrawDeck(2);
}

- 17
- 1
public List shufflelist(List list) { LetterClass tempelement; List templist = new List(); List listcopy = new List(); int rand;
foreach (LetterClass item in list) { listcopy.Add(item); } while (listcopy.Count != 0) { rand = Random.Range(0, listcopy.Count); tempelement = listcopy[rand]; templist.Add(listcopy[rand]); listcopy.Remove(tempelement); } return templist; }

- 3
- 2
-
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 29 '23 at 06:01
-
To be a strictly valid answer, this block needs to operate generically on `List
`. From the first glance, it suffices to replace all entries of type `List` for it. Also, it makes sense to fix code block formatting and make a brief description of algorithm before the block. – P. Frolov Mar 30 '23 at 12:38
private List<GameObject> ShuffleList(List<GameObject> ActualList) {
List<GameObject> newList = ActualList;
List<GameObject> outList = new List<GameObject>();
int count = newList.Count;
while (newList.Count > 0) {
int rando = Random.Range(0, newList.Count);
outList.Add(newList[rando]);
newList.RemoveAt(rando);
}
return (outList);
}
usage :
List<GameObject> GetShuffle = ShuffleList(ActualList);
Old post for sure, but I just use a GUID.
Items = Items.OrderBy(o => Guid.NewGuid().ToString()).ToList();
A GUID is always unique, and since it is regenerated every time the result changes each time.

- 8,198
- 71
- 51
- 66

- 75
- 1
- 2
-
10This answer has already been given, and worse it is designed for uniqueness not randomness. – Alex Angas Jan 04 '16 at 22:21
A very simple approach to this kind of problem is to use a number of random element swap in the list.
In pseudo-code this would look like this:
do
r1 = randomPositionInList()
r2 = randomPositionInList()
swap elements at index r1 and index r2
for a certain number of times

- 7,981
- 3
- 36
- 42
-
2One problem with this approach is knowing when to stop. It also has a tendency to exaggerate any biases in the pseudo-random number generator. – Mark Bessey Nov 07 '08 at 19:58
-
3Yes. Highly inefficient. There is no reason to use an approach like this when better, faster approaches exist that are just as simple. – PeterAllenWebb Nov 07 '08 at 21:25
-
1not very efficient or effective... Running it N times would likely leave many elements in their original position. – NSjonas Dec 07 '12 at 21:46