Linq MaxBy 带有所有元素的实现?

5
我希望获取枚举中所有属性值最大的元素:
IEnumerable<Person> allOldest = people.GroupBy(p => p.Age)
    .OrderByDescending(i=>i.Key).First().Select(_=>_);

.NET 6引入了MaxBy,它返回最大项:

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

MaxBy 对我没用吗?还有比第一个例子更优雅的解决方案吗?


2
你是否认为只遍历一次输入很重要?如果不是,你可以使用 Max 来获取最大值,然后使用 Where 获取所有具有该值的元素。 - Jon Skeet
谢谢Jon。为什么不呢?但是它比一次迭代更优化吗? 我认为大枚举和多次循环,如果适用的话,可以在SQL中进行EF转换。 - NewTom
我不确定你所说的“比1次迭代更优化”的意思 - 如果你需要这个针对EF,请在问题中说明,因为这可能会使得其他答案都不适用。 - Jon Skeet
3个回答

5

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

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

好的,但 maxItems 是 IGrouping<int, Person> 类型,请在 for 循环之后使用 Select(=>) 来选择 Person。 - NewTom
我重构了我的答案,请看一下。 - Ran Turner
这种方法的潜在问题是 items 被枚举两次。如果 items 是一个延迟的可枚举对象,连接到数据库或其他非内存数据源,则可能会出现问题。 - Theodor Zoulias
@TheodorZoulias,甚至不止两次,而是items.Count() + 1次,这更糟糕 =) - Guru Stron
1
@GuruStron,你说得对。但在Ran Turner的最新编辑之后,我的初始评论仍然成立。 - Theodor Zoulias

1
如果您可以接受为项目添加外部依赖项,您可以安装备受尊敬的MoreLinq软件包(由唯一的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 中,这很可能会导致名称解析冲突。


0

这是一个情况,linq 不一定是最好的选择。您可以创建一个 linq 风格的扩展来实现它,但实际上最直接的解决方案就是编写一个函数。这里有一个简单的示例。我使用了一个值元组作为人员对象的替代品。

    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})");
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接