How to get the maximum object of a group by criteria (the whole object, not its property)

I want to get the maximum object IGrouping

by some criteria, however, so far I cannot find an overload that will allow me to return the entire object within a group

List<Player> players = new List<Player>() 
{ 
     new Player() { Name = "Peyton Manning", Age = 36, Position = "QB", Salary = 19000000 },
     new Player() { Name = "Tom Brady", Age = 35, Position = "QB", Salary = 18400000 },
     new Player() { Name = "Drew Brees", Age = 34, Position = "QB", Salary = 21000000 },
     new Player() { Name = "Randy Moss", Age = 35, Position = "WR", Salary = 7000000 },
     new Player() { Name = "Marvin Harrison", Age = 38, Position = "WR", Salary = 11000000 },
     new Player() { Name = "Demaryius Thomas", Age = 23, Position = "WR", Salary = 5000000 },
     new Player() { Name = "Ryan Clady", Age = 26, Position = "OT", Salary = 10000000 },
};

      

I would like to write a query that returns a result set that I can list as follows:

foreach(Player player in highestPaidPlayers) 
{
      Console.WriteLine("The highest paid {0} is {1}, who is being paid {2}", player.Position, player.Name, player.Salary);
}

      

So far this is all I got:

var playersGroupedByPosition = players
    .GroupBy(p => p.Position)
    .Select(g => g.Max(p => p.Salary));

      

But this will give me a list of the highest salaries (like a list of integers). There doesn't seem to be an overload for Max

that allows me to return an object Player

from IGrouping

other than Max()

that relies on the object to implement IComparable

.

My LINQ is a little weak, so I didn't figure out how to write a sub-query to get the maximum group record and return it to the outer selection, but is there an easier way to do this?

I've seen solutions that reference the third party MoreLINQ library (and its custom operator MaxBy

), but I don't want to go that route (yet) if it can't be done with an existing set of query operators, and if not, I'd like to understand the limitation of existing operators to avoid doing this in the request.

+3


source to share


2 answers


Solution using a nested "subheading"

Syntactic solution of the expression:

var highestPaidPlayers = players.GroupBy(p => p.Position)
                                 .Select(x => x.Where(p => p.Salary == x.Max(m => m.Salary)).First());

      



Syntactic solution to the query:

var highestPaidPlayers = from pl in players
                         group pl by pl.Position
                         into g
                             let max = g.Max(x => x.Salary)
                             let maxPl = g.Where(x => x.Salary == max).First()
                             select maxPl;

      

Try Ideone .

+2


source


I think with ToList

and OrderBy

you can avoid using third party code:



IEnumerable<Player> highestPaidPlayers = players.GroupBy(p => p.Position)
    .Select(g => g.ToList().OrderBy(p => p.Salary).Last());

      

+4


source







All Articles