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