具有所有元素的 Linq MaxBy?

Linq MaxBy with all elements?

我想获取可枚举中的所有元素,其 属性 是最大值:

IEnumerable<Person> allOldest = people.GroupBy(p => p.Age)
    .OrderByDescending(i=>i.Key).First().Select(_=>_);

.NET 6 介绍 MaxBy 其中 return 最大项目:

Person uniqueOldest = people.MaxBy(person => person.Age);

MaxBy 帮不了我? 还有比第一个例子更优雅的解决方案吗?

使用 Max 是一种简单明了的方法:

var maxAge = items.Max(y => y.Age);
var maxItems = items.Where(x => x.Age == maxAge);

如果您愿意为项目添加外部依赖项,则可以安装可敬的 MoreLinq package (originally developed by the one and only Jon Skeet) 并执行此操作:

IEnumerable<Person> allOldest = MoreLinq.MoreEnumerable.MaxBy(people, p => p.Age);

MoreEnumerable.MaxBy方法的签名:

public static IExtremaEnumerable<TSource> MaxBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> selector);

您也可以尝试将其用作扩展方法,方法是在顶部添加此 using 指令:

using static MoreLinq.Extensions.MaxByExtension;

...但是在 .NET 6 中,这将(很可能)导致名称解析冲突。

这是 linq 不一定是最佳选择的时代之一。您可以创建一个 linq 样式扩展来执行此操作,但实际上最直接的解决方案就是编写一个函数。这是一个简单的例子。我使用值元组代替您的 person 对象。

    static void Main(string[] _)
    {
        var source = new (int key, int value)[] { (0, 0), (1, 5), (2, 1), (3, 5), (4, 0), (5, 5) };

        var allMax = new List<(int, int)>();
        int currentMax = int.MinValue;

        foreach (var (key, value) in source)
        {
            if (currentMax < value)
            {
                allMax.Clear();
                allMax.Add((key, value));
                currentMax = value;
            }
            else if (currentMax == value)
            {
                allMax.Add((key, value));
            }
        }

        Console.WriteLine($"{allMax.Count} Max valued items found");

        foreach (var (key, value) in allMax)
            Console.WriteLine($"({key}, {value})");
    }