You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Linq获取属性为最大值的所有元素,有无比分组排序更优雅的方案?

问题解答

原生MaxBy确实无法直接实现返回所有最大值元素的需求,它的设计逻辑是当存在多个符合最大值条件的元素时,仅返回序列中第一个匹配的元素。以下是两种比分组排序更优雅、性能更好的实现方案:


方案1:结合最大值属性过滤(实现最简,两次遍历)

这个方案时间复杂度为O(n),远低于原分组排序实现的O(n log n),集合元素量越大性能优势越明显:

// 先取到最大年龄值
int? maxAge = people.MaxBy(p => p.Age)?.Age;
// 过滤所有年龄等于最大值的元素
IEnumerable<Person> allOldest = maxAge.HasValue ? people.Where(p => p.Age == maxAge.Value) : Enumerable.Empty<Person>();

方案2:自定义扩展方法(性能最优,一次遍历)

如果要避免两次遍历集合(比如集合是延迟加载的远程数据源、或者元素量极大),可以自己实现通用的返回所有最大值元素的扩展方法:

public static IEnumerable<TSource> MaxAllBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer = null)
{
    comparer ??= Comparer<TKey>.Default;
    using var enumerator = source.GetEnumerator();
    if (!enumerator.MoveNext()) yield break;
    
    var currentMaxKey = keySelector(enumerator.Current);
    var maxElements = new List<TSource> { enumerator.Current };
    
    while (enumerator.MoveNext())
    {
        var currentKey = keySelector(enumerator.Current);
        var compareResult = comparer.Compare(currentKey, currentMaxKey);
        if (compareResult > 0)
        {
            currentMaxKey = currentKey;
            maxElements.Clear();
            maxElements.Add(enumerator.Current);
        }
        else if (compareResult == 0)
        {
            maxElements.Add(enumerator.Current);
        }
    }
    
    foreach (var element in maxElements)
    {
        yield return element;
    }
}

使用方式非常简洁:

IEnumerable<Person> allOldest = people.MaxAllBy(p => p.Age);

内容的提问来源于stack exchange,提问作者NewTom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 04:54:09