五、聚合与数值计算

用于合并元素计算统计值。这类操作能快速从序列中提取关键信息(如最大值、总和、自定义累积结果),是数据分析和统计场景的核心工具。

1. Max() / Min() / Sum() / Average()

返回序列的最大 / 最小 / 和 / 平均值(仅适用于数值类型,或对象中可转为数值的属性)。

性能特性:需遍历整个序列(O (n) 复杂度),对空序列的处理因方法而异(如 Sum 返回 0,Max 抛异常)。

典型场景:数值统计(如成绩总分、平均工资、最大订单金额)。

示例 1:基础数值序列
var scores = new List<int> { 80, 90, 75, 85, 95 };

// 最大值
int max = scores.Max(); // 95

// 最小值
int min = scores.Min(); // 75

// 总和
int total = scores.Sum(); // 425

// 平均值(返回 double)
double avg = scores.Average(); // 85.0
示例 2:对象集合的数值属性统计
public class Order {
    public int Id { get; set; }
    public decimal Amount { get; set; } // 订单金额(数值类型)
    public DateTime CreateTime { get; set; }
}

var orders = new List<Order> {
    new Order { Id = 1, Amount = 199.9m },
    new Order { Id = 2, Amount = 299.5m },
    new Order { Id = 3, Amount = 99.9m }
};

// 最大订单金额
decimal maxAmount = orders.Max(o => o.Amount); // 299.5m

// 订单总金额
decimal totalAmount = orders.Sum(o => o.Amount); // 599.3m

// 平均订单金额
double avgAmount = orders.Average(o => o.Amount); // ~199.77
注意:空序列处理
var emptyList = new List<int>();

// Sum() 对空序列返回 0(安全)
int sum = emptyList.Sum(); // 0

// Max()/Min()/Average() 对空序列抛 InvalidOperationException(需提前判断)
if (emptyList.Any()) {
    int max = emptyList.Max(); 
} else {
    // 处理空序列逻辑(如返回默认值)
}
2. MaxBy(keySelector) / MinBy(keySelector)(.NET 6+)

根据键选择器(如对象的某个属性)返回序列中键最大 / 最小的元素(返回元素本身,而非键值)。

性能特性:遍历一次序列(O (n) 复杂度),比先查键再找元素更高效。

典型场景:找 “年龄最大的用户”“价格最低的商品” 等(需返回元素而非单纯的键值)。

示例 1:基础对象集合
public class Person {
    public string Name { get; set; }
    public int Age { get; set; }
}

var people = new List<Person> {
    new Person { Name = "张三", Age = 25 },
    new Person { Name = "李四", Age = 30 },
    new Person { Name = "王五", Age = 22 }
};

// 按年龄找最大的人(返回 Person 对象)
Person oldest = people.MaxBy(p => p.Age); // 李四(30岁)

// 按年龄找最小的人
Person youngest = people.MinBy(p => p.Age); // 王五(22岁)
示例 2:复杂键选择
public class Product {
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int Stock { get; set; } // 库存
}

var products = new List<Product> {
    new Product { Name = "手机", Price = 3999, Stock = 50 },
    new Product { Name = "电脑", Price = 5999, Stock = 30 },
    new Product { Name = "平板", Price = 2999, Stock = 40 }
};

// 找库存最少的商品
Product leastStock = products.MinBy(p => p.Stock); // 电脑(30库存)

// 找单价最高的商品
Product mostExpensive = products.MaxBy(p => p.Price); // 电脑(5999元)
3. Aggregate

自定义累积操作(从初始值开始,按规则逐步合并元素)。支持灵活的聚合逻辑(如字符串拼接、复杂计算、多值累积)。

核心逻辑
Aggregate(初始值, (累积结果, 当前元素) => 新累积结果)

  • 从 “初始值” 开始,逐个处理元素,用 “累积函数” 更新结果,最终返回最终累积值。

性能特性:遍历一次序列(O (n) 复杂度),适合自定义聚合场景。

典型场景:字符串拼接、自定义求和(如带权重的累加)、多字段联合计算等。

示例 1:基础累积(模拟 Sum)
var numbers = new List<int> { 1, 2, 3, 4 };

// 累加所有元素(初始值 0,每次累加当前元素)
int sum = numbers.Aggregate(0, (currentSum, num) => currentSum + num); // 10(0+1+2+3+4)
示例 2:字符串拼接
var words = new List<string> { "Hello", "World", "C#", "LINQ" };

// 拼接成句子(初始值空字符串,每次追加当前单词+空格)
string sentence = words.Aggregate("", (currentStr, word) => currentStr + word + " ");
// 结果:"Hello World C# LINQ "(注意末尾有空格,可后续处理)

// 优化:去掉末尾空格
string trimmed = words.Aggregate("", (s, w) => $"{s}{(s == "" ? "" : " ")}{w}"); 
// 结果:"Hello World C# LINQ"
示例 3:复杂自定义聚合(多值计算)
public class Student {
    public string Name { get; set; }
    public int Score { get; set; }
}

var students = new List<Student> {
    new Student { Name = "张三", Score = 80 },
    new Student { Name = "李四", Score = 90 },
    new Student { Name = "王五", Score = 70 }
};

// 用 Aggregate 同时计算总分和平均分(返回匿名对象)
var result = students.Aggregate(
    new { Total = 0, Count = 0 }, // 初始值:总分0,数量0
    (acc, student) => new { 
        Total = acc.Total + student.Score, // 累加分数
        Count = acc.Count + 1 // 计数+1
    },
    acc => new { // 最终转换:计算平均分
        Total = acc.Total,
        Avg = (double)acc.Total / acc.Count
    }
);

Console.WriteLine($"总分:{result.Total},平均分:{result.Avg}"); // 总分:240,平均分:80

核心对比与注意事项

方法 核心逻辑 返回类型 适用场景
Max() 求序列最大值 数值(如 int、decimal) 基础数值 / 属性最大值统计
Min() 求序列最小值 数值 基础数值 / 属性最小值统计
Sum() 求序列总和 数值 求和(空序列返回 0)
Average() 求序列平均值 double 平均计算(空序列抛异常)
MaxBy(key) 按键找最大元素 序列元素本身 需返回 “元素” 而非键值时
MinBy(key) 按键找最小元素 序列元素本身 需返回 “元素” 而非键值时
Aggregate 自定义累积操作 自定义类型(由初始值决定) 复杂聚合(如拼接、多值计算)

关键注意事项

  1. 空序列处理
    • Sum() 对空序列返回 0;Max()/Min()/Average() 对空序列抛 InvalidOperationException(建议先通过 Any() 判断非空)。
    • MaxBy()/MinBy() 对空序列抛异常;Aggregate 若为空序列,直接返回初始值。
  2. 非数值类型兼容
    • Max()/Min() 支持实现 IComparable 的非数值类型(如 string 按字典序比较)。
      示例:new List<string> { "b", "a", "c" }.Max() → “c”(字典序最大)。
  3. 性能优化
    • 简单统计优先用 Max/Sum 等内置方法(底层优化更高效);复杂逻辑再用 Aggregate
    • MaxBy/MinBy 比 “先查键再找元素” 更高效(仅遍历一次)。
Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐