获取排名的 linq 问题

Posted

技术标签:

【中文标题】获取排名的 linq 问题【英文标题】:linq issue to get a ranking 【发布时间】:2021-06-05 07:37:58 【问题描述】:

我很难获得用户在列表中的排名。

我的列表如下所示:

User Score
1 10
2 10
1 5
3 5
2 40
1 10

我尝试获取用户 3 的排名。

为此,我使用按用户 ID 分组的第一个 linq 请求。

然后我请求将分数(nbpoints)和 orderby 像这样降序求和:

用户 2 获得 50 分 用户 1 有 25 分 用户 3 获得 5 分

那么如何获取用户的排名呢?我用 select 尝试了索引,但它在排序之前使用了索引。

我的要求如下:

 MyScoreRankObject = users.Select((u, index) =>
                  
                      return new StatResultDto
                      
                          ActualScore = u.Sum(s => s.NbPoints),
                          Index = u.Index
                    ;
                  ).OrderByDescending(s => s.ActualScore).Where(u => u.Id ==3).FirstOrDefault();

我怎样才能获得排名?

我试图得到:

对用户 3 的请求给了我对象:

new StatResultDto
                      
                          ActualScore = u.Sum(s => s.NbPoints),
                          Index = u.Index // Gives the ranking
                    ;

谢谢,

【问题讨论】:

这能回答你的问题吗? How to get the index of an item in a list in a single step? 【参考方案1】:

我为其他苦苦挣扎的人找到了解决方案。不确定最好的一个。如果你有更好的我接受。我在 order by 之后添加了此代码。

.Select((u, index) =>
                  
                      u.Rank = index + 1;
                      return u;
                  )

最终解决方案:

 MyScoreRankObject = users.Select((u) =>
              
                  return new StatResultDto
                  
                      ActualScore = u.Sum(s => s.NbPoints)
                ;
              ).OrderByDescending(s => s.ActualScore).Select((u, index) =>
                  
                      u.Rank = index + 1;
                      return u;
                  ).Where(u => u.Id ==3).FirstOrDefault();

【讨论】:

您无需再执行最后两个步骤 Select & Where 。查看My answer了解更多详情。【参考方案2】:

Demo on dotnetfiddle

其实你只是GroupBy 然后OrderByDescending

var groupByandSortedData = myData.GroupBy(r => r.UserId)
                            .Select(g => new  User = g.Key, ActualScore = g.Sum(s => s.NbPoints) )
                            .OrderByDescending(p => p.ActualScore);

最后,您可以通过ranking 使用以下3 种方式获取您的数据:

var ranking = 3;
Console.WriteLine(groupByandSortedData.Skip(2).FirstOrDefault());
Console.WriteLine(groupByandSortedData.ElementAtOrDefault(ranking-1));  // due to index starting from 0 
Console.WriteLine(groupByandSortedData.ToList()[ranking-1]);

输出

 User = 3, ActualScore = 5 
 User = 3, ActualScore = 5 
 User = 3, ActualScore = 5 

在性能方面

我更喜欢第一种和第二种方式而不是第三种方式。因为最后一种方法已经执行了所有数据并加载到内存中。

【讨论】:

感谢您的回复,但我不想获得第三个。我想知道用户3是哪个排名。

以上是关于获取排名的 linq 问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 linq 实现密集秩

使用 LINQ 在 selectman 子查询中进行聚合

MySQL,获取用户排名

使用 MySQL 获取用户排名

如何使用 LINQ 在 XML 中按名称获取元素

使用 LINQ 获取连接表中的最大计数