Linq MaxBy 与所有元素?

Posted

技术标签:

【中文标题】Linq MaxBy 与所有元素?【英文标题】:Linq MaxBy with all elements? 【发布时间】:2021-11-06 10:23:12 【问题描述】:

我想获取属性最大的可枚举的所有元素:

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 帮不了我? 还有比第一个例子更优雅的解决方案吗?

【问题讨论】:

只对输入进行一次迭代对您来说很重要吗?如果没有,您可以使用Max 获取最大值,然后使用Where 获取具有该值的所有元素。 谢谢乔恩。为什么不。但它是否比 1 次迭代更优化?我认为大枚举和很多次,如果适用的话,在 SQL 中进行 EF 转换 我不确定您所说的“比 1 次迭代更优化”是什么意思 - 如果您需要为 EF 提供此功能,请在问题中说明,因为它可能会产生许多其他答案不合适。 【参考方案1】:

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

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

【讨论】:

好的,但是 maxItems 是 IGrouping 在选择 Person 之后使用 Select(=>) 我重构了我的答案,请看一下。 这种方法存在枚举items两次的潜在问题。如果 items 是一个延迟枚举,连接到数据库或其他一些非内存数据源,这可能是一个问题。 @TheodorZoulias 甚至不是两次,而是items.Count() + 1 次,这要糟糕得多 =) @GuruStron 你是对的。但是在 Ran Turner 的最新编辑之后,我最初的评论仍然成立。 ?【参考方案2】:

如果您可以在项目中添加外部依赖项,则可以安装受人尊敬的 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 中,这将导致(很可能)名称解析冲突。

【讨论】:

【参考方案3】:

这是 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)");
    

【讨论】:

以上是关于Linq MaxBy 与所有元素?的主要内容,如果未能解决你的问题,请参考以下文章

通过LINQ将函数应用于集合的所有元素[重复]

如何从列表数组(linq 列表)C# 中的所有元素调用方法

linq中where与skipwhile区别

C# 使用 LINQ 将 List<string> 的所有元素替换为相同的模式

LINQ:不是任何与所有都不是

.NET 6 带有实体框架的新 LINQ 功能