Randomizing Order of Your List or Array using LINQ

Perhaps you've got a collection of objects that you want ordered/sorted. I recently did. Perhaps you want them displayed in a non-deterministic manner or sorted randomly each time you write to an HTML view or otherwise consume that collection.


So imagine we're working with a List of Customers.


Problem being, we don't really have anything non-deterministic to work with. We could do this in SQL:

        (sin(Cust.ID * rand())) AS R
   FROM Cust

This though, puts your presentation logic in your data tier. Maybe you don't care, maybe it's not a big price to pay. I wanted to take it up to the presentation tier and do this sorting right before binding or writing these objects to the page.
Taking the lead from Bruno Silva, I immediately realized this was the seed of the algorithm that I was looking for. Here's my modification of Bruno's algorithm:

var r = new Random();

The call to r.Next() is obviously the key. Each object as it is evaluated in the OrderBy() will get a new random number associated with it. Celebrate good times!

Turn It Into an Extension Method

I haven't written much here about how much I love extension methods in the .NET CLR 3.0. I can't count the number of times that I've created a static 'utility' method that did something like this:

  • take in an object of some kind.
  • modify it.
  • return it back to the caller.
  • caller reassigns the return back into the object that it calls.

Rather than the above, I've created an extension method that I'll be able to call whenever for any collection that implements IEnumerable<t>. It's trivial then to write the extension method for IQueryable.

ExtensionMethod I've submitted my Randomize() extension method over at ExtensionMethod.net. What a great site, by the way, kudos to those guys for taking user submissions and helping grow the use of this feature in .NET.

public static IEnumerable<t> Randomize<t>(this IEnumerable<t> target){       
    var r = new Random();
    return target.OrderBy(x=>(r.Next()));