0

I have a list that I want to sort into a random order each time.

There are a few ways that I've come across:

  1. list = list.OrderBy(x => Guid.NewGuid()).ToList();
    
  2. var rnd = new Random();
    myList = myList.OrderBy(x => rnd.Next()).ToList();
    
  3. static Random random = new Random();
    
    public static IEnumerable<T> RandomPermutation<T>(IEnumerable<T> sequence)
    {
        T[] retArray = sequence.ToArray();
    
        for (int i = 0; i < retArray.Length - 1; i += 1)
        {
            int swapIndex = random.Next(i + 1, retArray.Length);
            T temp = retArray[i];
            retArray[i] = retArray[swapIndex];
            retArray[swapIndex] = temp;
        }
    
        return retArray;
    }
    

Obviously there's a big difference in the amount of code between 1 and 3, but are there any benefits?

svick
  • 236,525
  • 50
  • 385
  • 514
dotnetnoob
  • 10,783
  • 20
  • 57
  • 103
  • The first two are wrong and will not work reliably. – SLaks May 17 '13 at 18:29
  • 1
    http://stackoverflow.com/search?q=shuffle+list+[C%23] – SLaks May 17 '13 at 18:30
  • [Most efficient way to randomly “sort” (Shuffle) a list of integers in C#](http://stackoverflow.com/questions/375351/most-efficient-way-to-randomly-sort-shuffle-a-list-of-integers-in-c-sharp) – Damith May 17 '13 at 18:32
  • Guids are a source of *uniqueness*; they are not necessarily a source of *randomness*. – Eric Lippert May 17 '13 at 18:33
  • @SLaks The first one is, the second one is not, it's just less efficient. Well, I suppose technially there's a very, very small bias towards the order they are originally in, as it uses a stable sort, whereas the third option doesn't have that very slight bias, but so long as the number of items doesn't get anywhere near the number of total ints that shouldn't be an issue. – Servy May 17 '13 at 18:34

1 Answers1

7

The first one is just badness. GUIDs are unique, but they are not necessarily random. While some GUID implementations may rely on randomness, others won't. The result here is that the exact same program run on one machine will work and on another won't. That's really bad as it means you'll test your program, it will come out fine, you'll ship it, and things will break.

The third is a pretty standard shuffling algorithm. It's generally what I'd go with when solving this problem.

The second option will work, but it's noticeably less efficient than the third option. Sorting has a higher asymptotic complexity than the third algorithm you've shown there (O(n*log(n)) instead of O(n)).

If you had to write the code every single time you wanted to use it there may be value in the method that's 2 lines instead of a dozen, but when you only need to write it once and simply reference that general purpose shuffle method any time you need to shuffle a sequence you can justify using the semantically proper and more efficient code. (After all it's not that long or complex.)

Servy
  • 202,030
  • 26
  • 332
  • 449