如何使用LINQ选择具有最小或最大属性值的对象
如何使用LINQ选择具有最小或最大属性值的对象
我有一个具有可空DateOfBirth属性的Person对象。是否有一种使用LINQ查询Person对象列表中具有最早/最小DateOfBirth值的方法?
这是我开始的:
var firstBornDate = People.Min(p => p.DateOfBirth.GetValueOrDefault(DateTime.MaxValue));
空的DateOfBirth值设置为DateTime.MaxValue以将其排除在Min考虑范围之外(假设至少有一个指定了DOB)。
但是,这只是为我设置了一个DateTime值的firstBornDate。我想得到的是与之匹配的Person对象。我是否需要编写第二个查询,如下所示:
var firstBorn = People.Single(p=> (p.DateOfBirth ?? DateTime.MaxValue) == firstBornDate);
还是有一种更优雅的方法?
admin 更改状态以发布 2023年5月22日
不幸的是,没有内置的方法可以实现这个功能,但自己实现也很容易。以下是实现的关键:
public static TSource MinBy(this IEnumerable source, Func selector) { return source.MinBy(selector, null); } public static TSource MinBy (this IEnumerable source, Func selector, IComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (selector == null) throw new ArgumentNullException("selector"); comparer ??= Comparer .Default; using (var sourceIterator = source.GetEnumerator()) { if (!sourceIterator.MoveNext()) { throw new InvalidOperationException("Sequence contains no elements"); } var min = sourceIterator.Current; var minKey = selector(min); while (sourceIterator.MoveNext()) { var candidate = sourceIterator.Current; var candidateProjected = selector(candidate); if (comparer.Compare(candidateProjected, minKey) < 0) { min = candidate; minKey = candidateProjected; } } return min; } }
用法示例:
var firstBorn = People.MinBy(p => p.DateOfBirth ?? DateTime.MaxValue);
请注意,如果序列为空,这将抛出异常,如果有多个元素具有最小值,则返回具有最小值的第一个元素。
或者,您可以使用我们在MoreLINQ中提供的实现,在MinBy.cs中。(当然也有相应的MaxBy
。)
通过包管理器控制台安装:
PM> Install-Package morelinq