Answered Get a random List with LINQ?

  • Tuesday, September 08, 2009 9:59 AM
     
     

    Hello,

    I call in my application a webservice, who returns me a List of Persons (List<Person>) for e.g.!

    My question is now....can I get a randomized list of it with a LINQ-Statement? For e.g., when I have 5 items in my list, that the originally item 5 is on position 1 and item 3 ist after randomizing on position 4 and so on.

     

    Best Regards

    Echo6

All Replies

  • Tuesday, September 08, 2009 11:38 AM
     
     

    you should just be able to order by a random number:

    Random rand = new Random();

    from p in person
    orderby rand.Next()
    select p;

    i dunno, give it a shot.

  • Tuesday, September 08, 2009 12:02 PM
     
     

    Linq does not have any randomization but you can create your own extension method and use it against your data.

    Check this sample code found on the web (have to be tested) :

     

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using LinqRandom;

    namespace Program

    {

    class Program

    {

    static void Main(string[] args)

    {

    var x = new[] { 23, 303, -2332, 338, 8000, 100123, 254, 2234, 980, -90 };

    Console.WriteLine("Count of Items:{0}", x.Count());

    int count = 0;

    foreach (var y in x.Radomized())

    {

    Console.WriteLine("Item #{0}:{1}", count++, y);

     

    }

    }

    }

    }

    //End Sample project begin extension methods class

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    namespace LinqRandom

    {

    public static class Class1

    {

    public static T NextRandom<T>(this IEnumerable<T> source)

    {

    Random gen = new Random((int)DateTime.Now.Ticks);

    return source.Skip(gen.Next(0, source.Count() - 1) - 1).Take(1).ToArray()[0];

    }

    public static IEnumerable<T> Radomized<T>(this IEnumerable<T> source)

    {

    List<T> Remaining = new List<T>(source);

    while (Remaining.Count >= 1)

    {

    T temp = NextRandom<T>(Remaining);

    Remaining.Remove(temp);

    yield return temp;

    }

    }

     

     

    }

    }

  • Tuesday, September 08, 2009 12:04 PM
     
     Answered

    And a second example, more krafty :

    List<Employee> list = new List<Employee>();
    
    list.Add(...);
    list.Add(...); ... list = list.OrderBy(emp => Guid.NewGuid()).ToList();
  • Wednesday, September 09, 2009 6:37 AM
     
     

    And a second example, more krafty :

    List<Employee> list = new List<Employee>();

    list.Add(...);
    list.Add(...); ...

    list = list.OrderBy(emp => Guid.NewGuid()).ToList();

     

    Thank you!

    This works perfect! Big Smile

     

    Best Regards

    Echo6


  • Monday, October 29, 2012 2:32 PM
     
     

    Actually, this code is problematic because it does not always return the same sort value for a given employee. Depending on the sort algorithm being employed, this could be inefficient or even hang completely.

    I wrote an article that presents a better way to do this.

    public static void Shuffle<T>(this IList<T> list, Random rand)
    {
        int count = list.Count;
        while (count > 1)
        {
            int i = rand.Next(count--);
            T temp = list[count];
            list[count] = list[i];
            list[i] = temp;
        }
    }

    You can view the entire article at Extending LINQ with Random Operations.

  • Monday, November 05, 2012 4:53 AM
     
     

    I agree that the code marked as 'Answer' is problematic.   Jonathan presents a good alternative.  If you want something that plays nicely in a TDD environment you could just sort on the HashCode

    var shuffled = rawList.OrderBy(a =>a.GetHashCode());

    This is not high quality cryptographically correct solution but will randomise the elements while doing it in repeatable way.


    Paul Linton