简体   繁体   English

Linq 用于使用 group 和 orderby 计算排名

[英]Linq for calculating rank with group and orderby

I am trying to calculate the rank of objects.我正在尝试计算对象的等级。 Since multiple objects can have the same score I would need to group them so they get the same rank.由于多个对象可以具有相同的分数,因此我需要对它们进行分组,以便它们获得相同的排名。

public class RankedItem {

  public string Name {get; set;}
  public int Score {get; set; }
  public int Rank {get; set; }

  public RankedItem(string name, int score) {
     Name = name;
     Score = score;
  }

}

public void CalculateRanks() {

  List<RankedItem> items = new List<RankedItems> {
    new RankedItem("A", 3),
    new RankedItem("B", 2),
    new RankedItem("C", 3),
    new RankedItem("D", 1),
    new RankedItem("E", 2)
  };
 
  IOrderedEnumerable<IGrouping<int, RankedItems>> rankedItems = items.GroupBy(i => b.Score).OrderBy(g => g.Key);

  
}

How can I set the rank now, so that rank 1 will be assigned to the highest score?我现在如何设置排名,以便将排名1分配给最高分?

You have basically 2 options here.你在这里基本上有2个选择。 Linq or Loop. Linq 或循环。 For both options you should use OrderByDescending since your score rank relationship is inverse.对于这两个选项,您应该使用OrderByDescending ,因为您的分数排名关系是相反的。 Then you can use the index + 1 to assign the ranks.然后你可以使用 index + 1 来分配排名。

  1. Loop.环形。

for this option you need a collection to hold your groupings which can be iterated using the index [ ] operator.对于此选项,您需要一个集合来保存可以使用 index [ ]运算符进行迭代的分组。 This is not possible in IOrderedEnumerable .这在IOrderedEnumerable中是不可能的。 So I suggest to use a List :所以我建议使用List

List<IGrouping<int, RankedItem>> rankedItems = items.GroupBy(b => b.Score)
                                                    .OrderByDescending(g => g.Key)
                                                    .ToList();

Now you can simply loop through the list having the index and loop again through all elements of each group to use the index to assign the rank:现在您可以简单地遍历具有索引的列表并再次遍历每个组的所有元素以使用索引来分配排名:

for (int i = 0; i < rankedItems.Count(); i++)
{
    IGrouping<int, RankedItem> grouping = rankedItems[i];
    foreach (var element in grouping)
    {
        element.Rank = i + 1;
    }
}
  1. LINQ: LINQ:

Use the index in this Select overload statement and create new objects using your constructor:使用此Select重载语句中的索引并使用您的构造函数创建新对象:

List<RankedItem> rankedItems = items.GroupBy(b => b.Score)
                                    .OrderByDescending(g => g.Key)
                                    .SelectMany((item, index) => item.Select(inner => 
                                            new RankedItem(inner.Name, item.Key) {Rank = index + 1})
                                    ).ToList();

Outcome:结果:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM