我正在MVC中编写一个LinQ查询,根据他们的分数返回学生的等级
// Merge the LB lists to get aggregated List, allot dummy rank(0)
var a = leaderboard.ToDictionary((kvp => kvp.Key),
(kvp => kvp.Value.leaderboard)).Values.SelectMany(x => x).GroupBy(student => student.stId).Select(
g => new Leaderboard {
stId = g.Key,
stName = g.Select(x => x.stName).First(),
rank = 0,
score = g.Select(x => x.score).Sum(),
cName = g.Select(x => x.cName).First()
});
// Arrange the records in descending order of scores for rank
lbList = a.ToList().OrderByDescending(q => q.score).ToList();
int rank = 1;
lbList = lbList.Select(c => { c.rank = rank++; return c; }).ToList();
但是对于相同的分数,这会返回不同的等级。看作分数是唯一没有时间分量的参数,如何更改此分数以返回相同分数的相同排名?
答案 0 :(得分:0)
按顺序创建一个独特的分数集合,然后使用该集合中当前学生分数的位置作为他的排名:
var UniqueScores = a.OrderByDescending(x=>x.score).Select(x=>x.score).Distinct().ToArray;
lbList = lbList.Select(c => { c.rank = (UniqueScores.IndexOf(c.score) + 1); return c; }).ToList();
答案 1 :(得分:0)
这段代码看起来很可疑:
var a = leaderboard.ToDictionary((kvp => kvp.Key),
(kvp => kvp.Value.leaderboard)).Values.SelectMany(x => x).GroupBy(student => student.stId).Select(
g => new Leaderboard {
stId = g.Key,
stName = g.Select(x => x.stName).First(),
rank = 0,
score = g.Select(x => x.score).Sum(),
cName = g.Select(x => x.cName).First()
});
SelectMany(x => x)
。这有什么意义?它什么也没做。g.Select(x => x.cName).First()
。它不是最优的,也不是可读的:g.First().cName
。Values
。所以,我会像这样重写它:
var a = leaderboard.
Select(x => x.Value.leaderboard).
GroupBy(student => student.stId).
Select(
g => new Leaderboard {
stId = g.Key,
stName = g.First().stName,
rank = 0,
score = g.Sum(x => x.score),
cName = g.First().cName});
有一点需要考虑。您的代码以ToList()
结尾。如果你想将List<>
作为输出,那么简单的for循环是我认为最好的解决方案:
var lbList = a.OrderByDescending(x => x.score);
int rank = 1;
for (int i = 0; i < lbList.Count; ++i)
{
if (i > 0 && lbList[i - 1].score != lbList[i].score)
++rank;
lbList[i].rank = rank;
}
如果您需要lbList
作为IEnumerable<>
,那么:
var lbList = a.
GroupBy(q => q.score).
OrderByDescending(g => g.Key).
SelectMany(
(group, index) => group.Select(s => {
s.rank = index + 1;
return s;
});