Coder Perfect

How can I get LINQ to return the object with the highest value for a particular property? [duplicate]

Problem

If I’m teaching a class that looks like this:

public class Item
{
    public int ClientID { get; set; }
    public int ID { get; set; }
}

And then there’s a collection of those things…

List<Item> items = getItems();

How can I get the single “Item” object with the highest ID using LINQ?

If I do something along the lines of:

items.Select(i => i.ID).Max(); 

When what I really want is the Item object itself with the highest ID, I’ll only get the highest ID. I’d like it to return a single “Item” object rather than an integer.

Asked by FrankTheTank

Solution #1

Only one time will this loop.

Item biggest = items.Aggregate((i1,i2) => i1.ID > i2.ID ? i1 : i2);

Thank you, Nick – I’ve sent the evidence.

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<Item> items1 = new List<Item>()
        {
            new Item(){ ClientID = 1, ID = 1},
            new Item(){ ClientID = 2, ID = 2},
            new Item(){ ClientID = 3, ID = 3},
            new Item(){ ClientID = 4, ID = 4},
        };
        Item biggest1 = items1.Aggregate((i1, i2) => i1.ID > i2.ID ? i1 : i2);

        Console.WriteLine(biggest1.ID);
        Console.ReadKey();
    }


}

public class Item
{
    public int ClientID { get; set; }
    public int ID { get; set; }
}  

Get the same result by rearranging the list.

Answered by Seattle Leonard

Solution #2

.OrderByDescending(i=>i.id).First()

Regarding the performance issue, this solution is almost certainly slower in theory than a linear approach. However, most of the time, we are not dealing with a large enough data collection to make a significant difference.

If speed is a priority, Seattle Leonard’s solution should provide linear time complexity. You might perhaps start with a new data structure that returns the maximum value item at a constant rate.

First() is similar to Take(1), except instead of returning an enumeration containing the item, it returns the item directly.

Answered by Codism

Solution #3

int max = items.Max(i => i.ID);
var item = items.First(x => x.ID == max);

Of course, this presupposes the items collection contains elements.

Answered by Nick Larsen

Solution #4

Use the morelinq project’s MaxBy:

items.MaxBy(i => i.ID);

Answered by tzaman

Solution #5

This is an extension method that was inspired by @Seattle Leonard’s response:

 public static T GetMax<T,U>(this IEnumerable<T> data, Func<T,U> f) where U:IComparable
 {
     return data.Aggregate((i1, i2) => f(i1).CompareTo(f(i2))>0 ? i1 : i2);
 }

Answered by Paul Richards

Post is based on https://stackoverflow.com/questions/3188693/how-can-i-get-linq-to-return-the-object-which-has-the-max-value-for-a-given-prop