IEnumerable的随机顺序

时间:2012-02-20 12:54:13

标签: c# c#-4.0 ienumerable

我有一个IEnumerable集合,如下所示

var result1 = GetResult1() // Returns 2,4,5,6

我必须以随机的方式处理元素并创建另一个集合,结果如下:

var result2 = GetResult2(result1) // Returns 2,4,5,6 in a random order.
// An example output would be 4,6,2,5 in the resultant collection.

我通过以下方式完成了这项工作:

var result1 = GetResult1();
var random = new Random();
var result2 = result1.OrderBy(order=>random.Next());

然而,问题是如果我访问result2,result2中的元素会再次被洗牌,即如果我将result2的结果输出到控制台两次,那么元素会再次被混淆。

请告诉你如何保持这种制服。一旦我处理了这个收藏品,它就应该保持相同的状态。我必须使用懒惰的评估,因为结果非常大。

3 个答案:

答案 0 :(得分:5)

您正在寻找随机播放算法

请参阅以下SO线程以提供良好的扩展方法来完成工作:

Is using Random and OrderBy a good shuffle algorithm?

An extension method on IEnumerable needed for shuffling


要回答你的问题“为什么会再次洗牌?”,这是因为OrderBy的工作方式(延迟执行)。你可以尝试:

var result2 = result1.OrderBy(order=>random.Next()).ToList();

答案 1 :(得分:1)

您可以像这样使用ToList()

var result2 = result1.OrderBy(order=>random.Next()).ToList();

答案 2 :(得分:1)

我发现你需要对结果进行延迟评估,如果是这种情况,你可以做的是:

var randomNumbers = result1.Select(r => random.Next()).ToArray();
var orderedResult = result1.Zip(randomNumbers, (r, o) => new { Result = r, Order = o })
    .OrderBy(o => o.Order)
    .Select(o => o.Result);

通过在随机数上调用ToArray(),这些不会改变。当您最终需要result中的项目时,您可以使用随机数,OrderBy随机数和Select结果来压缩项目。

只要result中的项目按相同顺序排列,orderedResult中的结果每次都应该相同。