LINQ中的Group by:困扰初学者的5个问题

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

LINQ中的Group by:通过实际示例理解分组

\n\n

如果你曾经用C#编写过针对集合的查询,那么你很可能遇到过这样的问题:“我该如何对数据进行分组?” LINQ中的group by 是Stack Overflow上最热门的话题之一(拥有数万次浏览)。这并非偶然:分组乍看起来很简单,但实际上,初学者常常会踩到一些典型的“坑”,比如如何选择组中的第一条记录、如何计算总和或进行嵌套分组。

\n\n

在本文中,我们将探讨关于 LINQ GroupBy 的5个最常见问题,并提供可行的解决方案。我们开始吧!

\n\n

1. LINQ中的GroupBy是如何工作的?基本语法

\n\n

GroupBy 方法类似于SQL中的GROUP BY语句。它根据指定的键将序列拆分为多个组。结果是一个 IGrouping<TKey, TElement> 对象的集合,其中每个对象包含一个键以及属于该组的所有元素。

\n\n

这是一个最简单的例子。假设我们有一个学生列表:

\n\n
public class Student\n{\n    public string Name { get; set; }\n    public string Group { get; set; }\n    public int Score { get; set; }\n}\n\nvar students = new List<Student>\n{\n    new Student { Name = "安娜", Group = "A", Score = 85 },\n    new Student { Name = "鲍里斯", Group = "B", Score = 90 },\n    new Student { Name = "维卡", Group = "A", Score = 78 },\n    new Student { Name = "格列布", Group = "B", Score = 92 }\n};
\n\n

按组名进行分组:

\n\n
var grouped = students.GroupBy(s => s.Group);\n\nforeach (var group in grouped)\n{\n    Console.WriteLine($"组: {group.Key}");\n    foreach (var student in group)\n    {\n        Console.WriteLine($"  {student.Name} — {student.Score}");\n    }\n}
\n\n

输出:

\n
组: A\n  安娜 — 85\n  维卡 — 78\n组: B\n  鲍里斯 — 90\n  格列布 — 92
\n\n

一切都很简单。但正如常言道,魔鬼在于细节。

\n\n

2. 如何从每个组中选择第一条记录?

\n\n

这是关于 LINQ中的group by 最常见的问题。假设我们需要从每个组中获取一名最佳学生(分数最高)。该怎么做?

\n\n

解决方案是将 GroupBy 与 First() 或 OrderByDescending 结合使用:

\n\n
var bestStudents = students\n    .GroupBy(s => s.Group)\n    .Select(g => g.OrderByDescending(s => s.Score).First());\n\nforeach (var student in bestStudents)\n{\n    Console.WriteLine($"{student.Name} — {student.Group} — {student.Score}");\n}
\n\n

结果:安娜(85)和格列布(92)。请注意:在 Select 内部,我们对组进行排序并取第一个元素。这就是“如何实现LINQ group by first”的答案。

\n\n

重要提示: 如果组为空,First() 会抛出异常。如果可能发生这种情况,请使用 FirstOrDefault()。

\n\n

3. 如何计算每个组的总和、计数或平均值?

\n\n

分组后,通常不仅需要遍历元素,还需要获取聚合值。例如,每个组的总分或平均分。

\n\n

使用 Sum、Count、Average:

\n\n
var groupStats = students\n    .GroupBy(s => s.Group)\n    .Select(g => new\n    {\n        Group = g.Key,\n        Count = g.Count(),\n        TotalScore = g.Sum(s => s.Score),\n        AverageScore = g.Average(s => s.Score)\n    });\n\nforeach (var stat in groupStats)\n{\n    Console.WriteLine($"组 {stat.Group}: {stat.Count} 名学生, 总分 {stat.TotalScore}, 平均分 {stat.AverageScore:F2}");\n}
\n\n

输出:

\n
组 A: 2 名学生, 总分 163, 平均分 81.50\n组 B: 2 名学生, 总分 182, 平均分 91.00
\n\n

也可以使用 Min 和 Max —— 在

博客

书籍推荐