C#中:从一个IEnumerable得到一个随机值优雅的代码 [英] C#: Elegant code for getting a random value from an IEnumerable
问题描述
在Python中,我可以这样做:
In Python, I can do this:
>>> import random
>>> ints = [1,2,3]
>>> random.choice(ints)
3
在C#我做的第一件事是:
In C# the first thing I did was:
var randgen = new Random();
var ints = new int[] { 1, 2, 3 };
ints[randgen.Next(ints.Length)];
不过,这需要建立索引, int的也重复
困扰我。所以,我想出了这一点:
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();
还是不太好,效率高。 ?有没有得到来自IEnumberable一个随机值更优雅的方式。
Still not very nice and efficient. Is there a more elegant way of getting a random value from an IEnumberable?
推荐答案
下面是给你一对夫妇的扩展方法:
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);
对于一般的IEnumerable< T>
,这将是O( N ),因为这是的复杂性.Count之间的()
和随机 .ElementAt( )
通话;然而,这两种特殊情况下为数组和列表,所以在这些情况下,这将是O(1)。
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).
这篇关于C#中:从一个IEnumerable得到一个随机值优雅的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!