如何随机订购 IEnumerable<>?

发布于 2024-11-18 20:13:43 字数 789 浏览 1 评论 0 原文

我有这个 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 />");
}

它每次都以相同的方式对列表进行排序:(

I have this IEnumerable :

IEnumerable<MyObject>

and I need to order the list of the MyObject randomly. Do I need to cast into an ArrayList?

Or I can do it directly? Thanks

EDIT

this is my actual random order function :

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 />");
}

it orders the list in the same way every time :(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

各空 2024-11-25 20:13:43
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();

请参阅这些链接以获取有关此解决方案的潜在问题的更多背景信息(主要是当前示例的性能下降,但也存在非-均匀分布):

IEnumerable<int> ints;

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

The ToList is only there to ensure that the same (random) order is returned when iterating over shuffled more than once. Of course you can shuffle 'inplace' if you don't need the original anymore

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

Update

There is some discussion on whether you should rely on OrderBy comparing elements only once. If you don't want to do trust your .NET implementation to do that, spell it out:

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

See these links for more background on what potential problem this solves (mainly a performance degradation for the current sample, but also the risk of having non-uniform distribution):

小…楫夜泊 2024-11-25 20:13:43

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

[编辑] 示例:(

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;

我尚未测试示例代码。)

Enumerators allow "iterated" access only. Thus, there is no possibility to access the elements randomly or in a sorted way. You have to read the enumerated values and (temporarily) store them in another list for which you can apply your (random) sorting algorithm.

[edit] Example:

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;

(I have not tested the example code.)

丘比特射中我 2024-11-25 20:13:43

您不能将 IEnumerable强制转换为其他类型 - 并且您也不想转换为非泛型无论如何,ArrayList类型。

但是,您可以做的是将所有内容读入列表(使用ToList扩展方法最简单),然后对其进行洗牌。 我的回答有一个示例洗牌代码——诚然是在迭代器块内,但内容就在那里。

编辑:如果您每次都看到相同的顺序,我怀疑您在短时间内创建了 Random 的多个实例,并且它们都具有相同的种子。

请阅读本文了解详细信息和解决方法。

You can't just cast an IEnumerable<T> to a different type - and you wouldn't want to convert to the non-generic ArrayList type anyway.

However, what you can do is read everything into a list (simplest with the ToList extension method) and then shuffle that. My answer here has an example of the shuffle code - admittedly within an iterator block, but the guts are there.

EDIT: If you're seeing the same ordering every time, I suspect you're creating multiple instances of Random in a short space of time, and they've all got the same seed.

Read this article for details and workarounds.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文