结合两个LINQ查询的优雅方式
本文关键字:查询 方式 LINQ 两个 结合 | 更新日期: 2023-09-27 18:06:41
如何将这两个LINQ查询合并为一个?
var maxEndDate = lstDates.Select(s => s.EndDate).Max();
var record = lstDates.Where(s => s.EndDate == maxEndDate).First();
MaxBy
是你正在寻找的:http://code.google.com/p/morelinq/source/browse/trunk/MoreLinq/MaxBy.cs像这样使用它:
var record = lstDates.MaxBy(a => a.EndDate);
EDIT 1:正如Jason指出的那样,这个方法只在使用LINQ to Objects时使用。如果您正在对数据库进行查询(因此您正在使用LINQ to SQL或其他),则应该考虑使用不同的方法。
你的看起来很好读,但是,如果它不满足你,你总是可以在IQueryable
对象上调用AsEnumerable
,然后使用MaxBy
方法。
var record = lstDates.AsEnumerable().MaxBy(a => a.EndDate);
EDIT 2:您可以在查询中更改的一件事是第二个语句。尽量缩短它如下(为了避免使用Where
):
var record = lstDates.First(s => s.EndDate == maxEndDate);
var record = lstDates.OrderByDescending(d => d.EndDate).First();
注意,实际上最好使用而不使用 LINQ。只需循环遍历列表,跟踪最大日期和第一次发现该日期的项:
DateTime maxDate = default(DateTime);
YourClass maxItem = null;
foreach (var item in lstDates)
{
if (item.EndDate > maxDate)
{
maxDate = item.EndDate;
maxItem = item;
}
}
现在你只迭代一次,而不必承受排序的打击。
这确实假设您正在使用LINQ-to-Objects。如果不是,那么这将从数据库(或其他地方)检索整个集合,这是不希望的。在这种情况下,我会使用你已经有的方法。
var record = (from r in lstDates
orderby r.EndDate descending
select r).First();
对于Link-to-Objects(在Linq-to-Sql中不支持聚合)。执行N(N)(好的,实际上是O(N +1))
var record = lstDates.Aggregate(lstDates.First(),
(mx, i) => i.EndDate > mx.EndDate ? i : mx));
对于那些阅读有困难的人来说,第一个参数是累加器的初始值,它将正常聚合列表中的值,但这里只是保存当前最高的记录。然后,对于列表中的每条记录,调用lambda函数,给出当前最高的项和下一个项。
var record = lstDates.Where(s => s.EndDate == lstDates.Max(v => v.EndDate)).First();