Reputation: 532
How can I combine these two LINQ queries in one?
var maxEndDate = lstDates.Select(s => s.EndDate).Max();
var record = lstDates.Where(s => s.EndDate == maxEndDate).First();
Upvotes: 8
Views: 186
Reputation: 103575
For Link-to-Objects (Aggregate not supported in Linq-to-Sql). Performs in N(n) (ok, actually O(n+1))
var record = lstDates.Aggregate(lstDates.First(),
(mx, i) => i.EndDate > mx.EndDate ? i : mx));
For those having trouble reading that, the first parameter is the initial value for the accumulator, which would normal aggregate values in the list, but here is just holding the current highest record. Then for each record in the list, the lambda function is called, given the current highest and the next item. It returns the new current highest.
Upvotes: 1
Reputation: 13039
MaxBy
is what you are looking for: http://code.google.com/p/morelinq/source/browse/trunk/MoreLinq/MaxBy.cs using it like this:
var record = lstDates.MaxBy(a => a.EndDate);
EDIT 1: As Jason pointed out this method is intended to be used only when you are working with LINQ to Objects. If you are querying against a database (and so you are using LINQ to SQL, or whatever) you should consider using a different approach.
Yours seems quite readable but, if it doesn't satisfy you, you could always call AsEnumerable
on the IQueryable
object and then use MaxBy
method.
var record = lstDates.AsEnumerable().MaxBy(a => a.EndDate);
EDIT 2: One thing you could change in your query is the second statement. Try to shorten it as follows (in order to avoid using Where
):
var record = lstDates.First(s => s.EndDate == maxEndDate);
Upvotes: 8
Reputation: 3372
var record = (from r in lstDates
orderby r.EndDate descending
select r).First();
Upvotes: 1
Reputation: 48596
Note that is actually best done without LINQ. Just loop through the list, keeping track of the maximum date, and the item at which that was first found:
DateTime maxDate = default(DateTime);
YourClass maxItem = null;
foreach (var item in lstDates)
{
if (item.EndDate > maxDate)
{
maxDate = item.EndDate;
maxItem = item;
}
}
Now you only iterate once, and don't have to take the hit of sorting.
This does assume that you're using LINQ-to-Objects. If you're not, then this will retrieve the entire collection from the database (or wherever) which is undesirable. In that case, I would just use the method you already have.
Upvotes: 1
Reputation: 6989
var record = lstDates.OrderByDescending(d => d.EndDate).First();
Upvotes: 2
Reputation: 4095
var record = lstDates.Where(s => s.EndDate == lstDates.Max(v => v.EndDate)).First();
Upvotes: -1