C#中:从一个IEnumerable得到一个随机值优雅的代码 [英] C#: Elegant code for getting a random value from an IEnumerable

查看:103
本文介绍了C#中:从一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆