当我想从DateTime
检索IEnumerable
属性中具有最高值的对象时,我可以执行以下操作:
var maxDate = myEnumerable.Max(x => x.TheDateTimeProperty);
var wantedObject = myEnumerable.FirstOrDefault(x => x.TheDateTimeProperty == maxDate);
这是否可以在不先获得maxDate
的情况下实现?例如:
var wantedObject = myEnumerable.GetByMaxDate(x => x.TheDateTimeProperty);
我知道我可以编写扩展方法GetByMaxDate
,但我想知道linq是否已经提供了一种方法。
只是为了澄清:没有寻找其他可能来写这个。如果存在一种方法,我只是感兴趣。 (代码少,代码管理的最佳性能)
答案 0 :(得分:11)
Pro:它应该与“any”linq提供程序(对象,实体,sql)一起使用
myEnumerable.OrderByDescending(x => x.TheDateTimeProperty).First();
Con:正如Matthew Watson在评论中指出的那样,它不会在(非常)大型名单上表现出色。
答案 1 :(得分:2)
我更喜欢像你原先说的那样首先获得maxDate。使用您已使用的语法时,我没有看到任何问题。
但是如果你想要,你可以像这样简写代码:
var wantedObject = myEnumerable.FirstOrDefault(x => x.TheDateTimeProperty == myEnumerable.Max(x => x.TheDateTimeProperty));
(此代码未经过测试,可能需要进行某些类型的转换)
或者您可以编写存储过程并从中获取数据。
但我不再喜欢OrderByDescending.First了。如果物理上表中的数据按指定的属性递增排序,则可以。但如果没有,那么你的sql表将需要进行降序排序,并可能从中获得高负载。特别是当表具有超过1m的记录并且DateTime以物理上升的方式存储时。
使用max可以获得比它更好(更快/更轻)的结果。
答案 2 :(得分:0)
由于没有其他答案,不在linq中存在内置方法,我会写下我将使用的内容。
对于linq到对象:
Habib在评论中提到的来自morelinq的方法MaxBy
。
对于linq to sql:
我会写一个扩展方法。我试过这个,但是下面的代码还没有用。 如果有人知道什么是错的,请编辑答案。我有空的时候会尝试搞清楚。
public static TSource SqlMaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
{
var maxValue = source.Max(selector);
return source.FirstOrDefault(selector == maxValue);
}