C#: Elegant code for getting a random value from an IEnumerable

c#

Solution

Here's a couple extension methods for you:

public static T RandomElement<T>(this IEnumerable<T> enumerable)
{
    return enumerable.RandomElementUsing<T>(new Random());
}

public static T RandomElementUsing<T>(this IEnumerable<T> enumerable, Random rand)
{
    int index = rand.Next(0, enumerable.Count());
    return enumerable.ElementAt(index);
}

// Usage:
var ints = new int[] { 1, 2, 3 };
int randomInt = ints.RandomElement();

// If you have a preexisting `Random` instance, rand, use it:
// this is important e.g. if you are in a loop, because otherwise you will create new
// `Random` instances every time around, with nearly the same seed every time.
int anotherRandomInt = ints.RandomElementUsing(rand);

For a general `IEnumerable<T>`, this will be O(n), since that is the complexity of `.Count()` and a random `.ElementAt()` call; however, both special-case for arrays and lists, so in those cases it will be O(1).

Problem

In Python, I can do this: ``` >>> import random >>> ints = [1,2,3] >>> random.choice(ints) 3 ``` In C# the first thing I did was: ``` var randgen = new Random(); var ints = new int[] { 1, 2, 3 }; ints[randgen.Next(ints.Length)]; ``` But this requires indexing, also the duplication of `ints` bothers me. So, I came up with this: ``` var randgen = new Random(); var ints = new int[] { 1, 2, 3 }; ints.OrderBy(x=> randgen.Next()).First(); ``` Still not very nice and efficient. Is there a more elegant way of getting a random value from an IEnumberable?

Original source

Related problems