C Sharp LINQ 分组(Grouping)
C# LINQ 分组(Grouping)[编辑 | 编辑源代码]
LINQ(Language Integrated Query) 是 C# 中用于查询数据的强大工具,而 分组(Grouping) 是其中一项核心功能,允许开发者按照指定的键(Key)将数据集合划分为多个逻辑组。分组操作在数据分析、报表生成和数据聚合等场景中非常有用。
基本概念[编辑 | 编辑源代码]
在 LINQ 中,分组操作通过 GroupBy
方法实现。该方法接受一个键选择器(Key Selector)函数,并返回一个分组集合,其中每个分组包含具有相同键的元素。
数学上,分组操作可以表示为: 其中:
- 是源数据集合,
- 是键选择器函数,
- 是分组键,
- 是分组后的结果。
基本语法[编辑 | 编辑源代码]
GroupBy
方法的基本语法如下:
IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
);
其中:
TSource
是源数据类型,TKey
是分组键的类型,keySelector
是一个函数,用于从元素中提取分组键。
示例代码[编辑 | 编辑源代码]
以下是一个简单的示例,展示如何使用 GroupBy
对一组学生按班级进行分组:
using System;
using System.Linq;
using System.Collections.Generic;
class Student
{
public string Name { get; set; }
public int Class { get; set; }
public int Score { get; set; }
}
class Program
{
static void Main()
{
List<Student> students = new List<Student>
{
new Student { Name = "Alice", Class = 1, Score = 85 },
new Student { Name = "Bob", Class = 2, Score = 90 },
new Student { Name = "Charlie", Class = 1, Score = 78 },
new Student { Name = "David", Class = 2, Score = 92 },
new Student { Name = "Eve", Class = 3, Score = 88 }
};
var groupedStudents = students.GroupBy(s => s.Class);
foreach (var group in groupedStudents)
{
Console.WriteLine($"Class {group.Key}:");
foreach (var student in group)
{
Console.WriteLine($"- {student.Name}, Score: {student.Score}");
}
}
}
}
输出:
Class 1: - Alice, Score: 85 - Charlie, Score: 78 Class 2: - Bob, Score: 90 - David, Score: 92 Class 3: - Eve, Score: 88
解释[编辑 | 编辑源代码]
1. 定义了一个 Student
类,包含学生的姓名、班级和分数。
2. 创建了一个 List<Student>
,包含 5 个学生数据。
3. 使用 GroupBy(s => s.Class)
按班级分组。
4. 遍历分组结果,打印每个班级的学生信息。
分组后的操作[编辑 | 编辑源代码]
分组后,可以对每个组进行进一步的操作,例如计算每组的平均值、最大值或最小值。
示例:计算每班的平均分[编辑 | 编辑源代码]
var averageScores = students.GroupBy(s => s.Class)
.Select(g => new
{
Class = g.Key,
AverageScore = g.Average(s => s.Score)
});
foreach (var item in averageScores)
{
Console.WriteLine($"Class {item.Class}, Average Score: {item.AverageScore}");
}
输出:
Class 1, Average Score: 81.5 Class 2, Average Score: 91 Class 3, Average Score: 88
多键分组[编辑 | 编辑源代码]
有时需要按多个属性分组。可以通过匿名类型实现多键分组。
示例:按班级和分数段分组[编辑 | 编辑源代码]
var multiKeyGroups = students.GroupBy(s => new
{
s.Class,
ScoreRange = s.Score >= 90 ? "High" : s.Score >= 80 ? "Medium" : "Low"
});
foreach (var group in multiKeyGroups)
{
Console.WriteLine($"Class {group.Key.Class}, Score Range: {group.Key.ScoreRange}");
foreach (var student in group)
{
Console.WriteLine($"- {student.Name}, Score: {student.Score}");
}
}
输出:
Class 1, Score Range: Medium - Alice, Score: 85 Class 1, Score Range: Low - Charlie, Score: 78 Class 2, Score Range: High - Bob, Score: 90 - David, Score: 92 Class 3, Score Range: Medium - Eve, Score: 88
实际应用场景[编辑 | 编辑源代码]
分组操作在以下场景中非常有用: 1. 报表生成:按部门、地区或时间分组统计销售数据。 2. 数据分析:按年龄、性别或兴趣分组用户行为数据。 3. 数据清洗:将数据按某种规则分组后处理异常值。
案例:电商订单分组[编辑 | 编辑源代码]
假设有一个订单列表,需要按客户 ID 分组,并计算每个客户的总消费金额:
var orders = new List<Order>
{
new Order { CustomerId = 1, Amount = 100 },
new Order { CustomerId = 2, Amount = 150 },
new Order { CustomerId = 1, Amount = 200 },
new Order { CustomerId = 3, Amount = 50 }
};
var customerSpending = orders.GroupBy(o => o.CustomerId)
.Select(g => new
{
CustomerId = g.Key,
TotalAmount = g.Sum(o => o.Amount)
});
foreach (var item in customerSpending)
{
Console.WriteLine($"Customer {item.CustomerId}, Total Spent: {item.TotalAmount}");
}
输出:
Customer 1, Total Spent: 300 Customer 2, Total Spent: 150 Customer 3, Total Spent: 50
性能注意事项[编辑 | 编辑源代码]
- 分组操作会遍历整个集合,时间复杂度为 O(n)。
- 对于大型数据集,可以考虑使用并行 LINQ(PLINQ)或数据库分组操作(如 SQL 的
GROUP BY
)。
总结[编辑 | 编辑源代码]
LINQ 分组是一个强大的功能,能够帮助开发者高效地组织和分析数据。通过 GroupBy
方法,可以轻松实现单键或多键分组,并结合其他 LINQ 操作(如 Select
、Sum
、Average
)进行复杂的数据处理。