如何使用LINQ选择具有最小或最大属性值的对象

20 浏览
0 Comments

如何使用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日
0
0 Comments

不幸的是,没有内置的方法可以实现这个功能,但自己实现也很容易。以下是实现的关键:

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

0