【问题标题】:C# Generic List<T> - How to Randomly Assign a "Rank" To Each Item?C# Generic List<T> - 如何为每个项目随机分配“等级”?
【发布时间】:2010-12-02 03:22:37
【问题描述】:

所以我有以下通用列表:

var topTenSomething = new List<Something>();

这里是一些东西:

public class Something
{
   public string Name { get; set; }
   public int Rank { get; set; }
}

所以我想随机分配“Rank”属性,但它需要从集合中的 1 个项目中排序。

所以如果集合有 3 个项目,我想从 1 到 3 随机分配排名:

  1. 一些名字
  2. 其他名称
  3. 别的东西

那么下一次,可能是:

  1. 其他名称
  2. 一些名字
  3. 别的东西

知道我的意思吗?

不知道该怎么做 - 有什么想法吗?

这是一个简单的研发原型 - 所以不要担心性能/我为什么要这样做。 (真实的将由数据库分配排名)

对 LINQ/非 LINQ 版本感到满意 - 只要它可以工作。

【问题讨论】:

  • 排名必须是唯一的吗?
  • 您要对集合进行排序吗?
  • @SLaks - 是的,最后。我在您的内容之后添加了该内容(请参阅下面我对您的回答的评论)。
  • 可以用它来填满一副牌

标签: c# linq collections random ranking


【解决方案1】:

像这样:

var rand = new Random();
var sequence = Enumerable.Range(0, list.Count).OrderBy(i => rand.Next()).ToList();

for(var i = 0; i < list.Count; i++)
    list[i].Rank = sequence[i];

如果您希望列表按随机排名排序:

var rand = new Random();
list.Sort((a, b) => rand.Next(-1, 2));    //Exclusive upper bound
for(var i = 0; i < list.Count; i++)
    list[i].Rank = i;

但是,这不是一个有效的顺序(a &lt; b 并不暗示b &gt; a)并且可能会导致意外结果。

【讨论】:

  • 我认为你的 OrderBy lamdba 将违反 IComparable 合同,当相同的 i 在重复调用中最终得到不同的值时。
  • @Joel:我不确定;我从来没有尝试过。请注意,这不是直接的 IComparable。
  • @Joel,它有效,我自己也做过类似的测试。不能对实现发誓,但大概每个项目的 lambda 结果都已缓存,因此不会重复可能昂贵的操作。
  • 是的,这行得通。我做了几个改变:1)做了list[i].Rank = sequence[i] + 1;(所以排名从1开始,而不是0)。还在末尾添加了OrderBy(x =&gt; x.Rank) 以对列表进行排序。但总而言之,它有效。谢谢。
  • @乔尔。 @Anthony:我检查了来源。 OrderBy 预先创建一个键数组;每次GetEnumerator 调用,每个元素都会只调用一次键选择器。
【解决方案2】:

这应该可行:

List<Something> somethings = new List<Something>();

/* TODO: populate list here... */

Random rand = new Random();
somethings.ForEach(s=>s.Rank = rand.Next(1, somethings.Count - 1));

【讨论】:

  • 我看到你希望它事后排序。添加这个:somethings = somethings.OrderBy(s => s.Rank).ToList();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 2018-12-16
  • 1970-01-01
相关资源
最近更新 更多