【问题标题】:Random Order of an IEnumerableIEnumerable 的随机顺序
【发布时间】:2012-02-20 12:54:12
【问题描述】:

我有一个 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 的结果输出到控制台两次,元素会再次被打乱。

请您建议如何保持这件制服。即,一旦我处理了收藏,之后它应该保持不变。不过,我必须使用惰性求值,因为结果非常庞大。

【问题讨论】:

标签: c# c#-4.0 ienumerable


【解决方案1】:

您正在寻找一种洗牌算法。

查看以下 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();

【讨论】:

  • 我投了反对票,因为他的 shuffle 的实现不是问题的重点
【解决方案2】:

我看到您需要对结果进行惰性评估,如果是这种情况,您可以这样做:

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(),这些不会改变。当您最终想要result1 中的项目时,您可以使用随机数压缩项目,OrderBy 随机数和Select 结果。

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

【讨论】:

  • 此解决方案仍将结果的原始大小加倍。内存方面,大致相当于实现IEnumerable。
  • 怎么样?如果result1 的每个元素都是一个包含很多字段的类,那就是很多数据。只有result1 的每个元素都包含一个整数大小的字段,它才会翻倍。我在这里给出的解决方案会消耗存储随机数的内存,但实际上获取结果数据是延迟的。
  • 谁说它们是对象?根据 OP,它们似乎是整数。
  • 啊,很好的观察@Marc,如果是这样,那么你是对的,这个解决方案实际上会使内存使用量翻倍。如果results1 来自服务器,此解决方案仍将限制命中和正在进行的数据传输量。
【解决方案3】:

你可以像这样使用ToList():

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

【讨论】:

  • 由于result1 的项目很大,所以询问者需要惰性/延迟评估。
  • 但是在某些时候它必须被枚举,因此提问者应该尽可能晚ToList()它,然后将结果集输出到任何需要它的地方
  • 如果提问者有某种形式的分页怎么办?即Skip(20).Take(10),那么客户端机器上的数据量会更少,但是如果在每次分页调用之前对OrderBy进行评估,则订单的结果会有所不同。
  • 好吧,我可以想到一个实现:一个有趣的报价网站,其中的报价是随机的,但报价永远不会显示超过一次。
猜你喜欢
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 2017-08-23
  • 2020-03-20
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
相关资源
最近更新 更多