如何随机排序IEnumerable<>?

时间:2011-07-04 09:14:40

标签: c# ienumerable

我有这个IEnumerable:

IEnumerable<MyObject>

我需要随机排序MyObject列表。我需要强制转换为ArrayList吗?

或者我可以直接做到吗?感谢

修改

这是我的实际随机顺序函数:

IList<ArchiePacchettoOfferta> list = new List<ArchiePacchettoOfferta>(m_oEnum);
for (int i = 0; i < list.Count; ++i)
{
    HttpContext.Current.Response.Write(list[i].Titolo + "<br />");
}

Random rnd = new Random();
for (int i = 0; i < list.Count; ++i)
{
    int swapIndex = rnd.Next(i + 1);
    ArchiePacchettoOfferta tmp = list[i];
    list[i] = list[swapIndex];
    list[swapIndex] = tmp;
}

for (int i = 0; i < list.Count; ++i)
{
    HttpContext.Current.Response.Write(list[i].Titolo + "<br />");
}

每次都以相同的方式命令列表:(

3 个答案:

答案 0 :(得分:6)

IEnumerable<int> ints;

var random = new Random();
var shuffled = ints.OrderBy(i => random.Next()).ToList();

ToList仅用于确保在多次调整迭代时返回相同(随机)顺序。当然,如果你不再需要原版,你可以随便洗牌“

ints = ints.OrderBy(i => random.Next()).ToList();

更新

有一些讨论是否应该仅依赖OrderBy比较元素一次。如果你不想信任你的.NET实现来做到这一点,请拼写出来:

var random = new Random();
var shuffled = ints
      .Select(i => new { key=random.Next(), i })
      .OrderBy(tmp => tmp.key)
      .Select(tmp => tmp.i)
      .ToList();

有关此解决的潜在问题的更多背景信息,请参阅以下链接(主要是当前样本的性能下降,以及不均匀分布的风险):

答案 1 :(得分:2)

您不能IEnumerable<T> 投射到其他类型 - 并且您不会希望转换为非通用{{1无论如何都要输入。

但是,可以做的是将所有内容读入列表(最简单的ArrayList扩展方法)然后随机播放。 My answer here有一个shuffle代码的例子 - 诚然在迭代器块中,但胆量就在那里。

编辑:如果你每次都看到相同的顺序,我怀疑你在很短的时间内创建了ToList的多个实例,而且他们都有相同的种子。

阅读this article了解详细信息和解决方法。

答案 2 :(得分:2)

枚举器仅允许“迭代”访问。因此,不可能随机地或以分类的方式访问元素。您必须读取枚举值并(暂时)将它们存储在另一个列表中,您可以为其应用(随机)排序算法。

[edit] 示例:

List<MyObject> list = new List<MyObject>( my_enumerable );
Random rnd = new Random(/* Eventually provide some random seed here. */);
for (int i = list.Count - 1; i > 0; --i)
{
    int j = rnd.Next(i + 1);
    MyObject tmp = list[i];
    list[i] = list[j];
    list[j] = tmp;
}
my_enumerable = list;

(我没有测试过示例代码。)