使用Linq单次迭代整数列表获取多聚合结果的正确语法是什么?
在单次迭代中用LINQ计算多个聚合值(Count、Max、Min、Average)
嘿,我完全懂你想一次性算出多个聚合值的需求——毕竟像你说的那种var avg = list.Average(); var max = list.Max();的写法,每调用一个聚合方法就会遍历一遍列表,数据量大的时候真的挺浪费性能的对吧?
你想要的是和SQL语句select Min(value), Max(value), Avg(value) from list等效的单次迭代效果,LINQ本身没有直接的内置方法,但我们可以用Aggregate方法或者自定义扩展方法来实现,这俩都能做到只遍历列表一次就拿到所有需要的聚合值。
方法一:用Aggregate直接实现
Aggregate是LINQ里专门用来做累积计算的方法,我们可以用它来在单次遍历中同时更新Count、Sum、Min、Max这些值,最后再算出Average:
// 假设list是你的整数列表IEnumerable<int> list var result = list.Aggregate( // 初始化累加器:Count初始0,Sum初始0,Min设为int最大值,Max设为int最小值 new { Count = 0, Sum = 0L, Min = int.MaxValue, Max = int.MinValue }, // 每遍历一个元素,更新累加器的各个值 (accumulator, currentNum) => new { Count = accumulator.Count + 1, Sum = accumulator.Sum + currentNum, Min = Math.Min(accumulator.Min, currentNum), Max = Math.Max(accumulator.Max, currentNum) }, // 最后从累加器计算出最终结果,处理空列表的情况 accumulator => new { Count = accumulator.Count, Min = accumulator.Count > 0 ? accumulator.Min : default(int), Max = accumulator.Count > 0 ? accumulator.Max : default(int), Average = accumulator.Count > 0 ? (double)accumulator.Sum / accumulator.Count : double.NaN } ); // 之后就可以直接用result.Count、result.Min、result.Max、result.Average了
方法二:自定义扩展方法(复用性更强)
如果需要多次用到这个功能,写一个自定义扩展方法会更方便,以后直接像调用LINQ内置方法一样使用:
public static class EnumerableExtensions { public static (int Count, int Min, int Max, double Average) GetAggregates(this IEnumerable<int> source) { if (source == null) throw new ArgumentNullException(nameof(source), "数据源不能为null"); int count = 0; long sum = 0; int min = int.MaxValue; int max = int.MinValue; foreach (var num in source) { count++; sum += num; if (num < min) min = num; if (num > max) max = num; } // 处理空列表的情况,这里可以根据你的业务需求调整返回值 if (count == 0) { return (0, default, default, double.NaN); } return (count, min, max, (double)sum / count); } }
使用的时候就非常简单了:
var aggregates = list.GetAggregates(); // 直接访问:aggregates.Count、aggregates.Min、aggregates.Max、aggregates.Average
需要注意的是,空列表的情况要特殊处理——比如Average会得到double.NaN,Min和Max你也可以根据业务需求返回null(如果改成可空int的话)或者抛出异常,完全看你的场景。
内容的提问来源于stack exchange,提问作者Sam Goldberg
相关产品推荐
相关产品推荐

