I have the following collection of scores;
var scores = new[]
{
new { score = 10, player = "Dave" },
new { score = 9, player = "Dave" },
new { score = 8, player = "Steve" },
new { score = 7, player = "Pete" },
new { score = 8, player = "Paul" },
new { score = 4, player = "Mike" }
};
I would like the a collection of scores containing the top 3 players and their high scores (ordered by score, highest score first) i.e.
{ score = 10, player = "Dave" }
{ score = 8, player = "Paul" }
{ score = 8, player = "Steve" }
This won't work;
var top3 = scores.OrderByDescending(s => s.score).Take(3);
This is because Dave has two of the top three scores and would appear twice.
Paul and Steve have the same score, for the purposes of this question I do not care which appears first in the list but there is a bonus up-vote for any solution that puts the person whose name appears first in the alphabet highest in the event that their scores are tied (to return results in the exact order shown in my example results).
The answer should use linq and lambda expressions
Thanks
If a player name should only appear once you have to group the collection by player and order each group by score. Then you can pick the highest 3.
var top3 = scores.GroupBy(x => x.player)
.Select(x => x.OrderByDescending(y => y.score).First())
.OrderByDescending(x => x.score)
.ThenBy(x => x.player)
.Take(3);
You can group them and then pick the maximum score of each player, and then order them:
var top3 = scores.GroupBy(x=>x.player)
.Select(g=>new
{
player=g.Key,
score=g.Max(p=>p.score)
})
.OrderByDescending(s => s.score)
.ThenBy(p=>p.player).Take(3);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With