0Pricing
C# Academy · 课时

OrderBy 与分组

对结果排序并分组

OrderBy 与分组 是 CoddyKit 上的免费 C# Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。

使用 OrderBy 排序

OrderBy 会根据您选择的键,以升序排列序列。lambda 返回用于排序的值。

它会返回一个新的已排序序列,并且排序稳定,这意味着键相同的元素会保留原有的相对顺序。

using System;
using System.Linq;

int[] nums = { 4, 1, 3, 2 };
var sorted = nums.OrderBy(n => n);
Console.WriteLine(string.Join(", ", sorted));

降序排列

OrderByDescending 会根据选定的键,从最大值到最小值进行排序。

请直接使用它,而不是先升序排序再反转;这样可以更清晰地表达意图,并在一次遍历中完成排序。

using System;
using System.Linq;

int[] scores = { 70, 95, 60, 88 };
var ranked = scores.OrderByDescending(s => s);
Console.WriteLine(string.Join(", ", ranked));

按属性排序

对于对象,请选择要依据其排序的属性。OrderBy(p => p.Age) 会将 people 按年龄从小到大排序。

键可以是任何可比较的类型——数字、字符串、日期——也可以是实现了 IComparable 的任意类型。

using System;
using System.Linq;
using System.Collections.Generic;

record P(string Name, int Age);
var people = new List<P> { new("Ana", 30), new("Bo", 22) };
var byAge = people.OrderBy(p => p.Age);
foreach (var p in byAge) Console.WriteLine(p.Name);

使用 ThenBy 进行次级排序

ThenBy 添加一个平局决胜条件。执行 OrderBy 后,它会根据第二个键,对主键相同的元素进行排序。

您可以链接多个 ThenBy/ThenByDescending 调用,实现多级排序。

using System;
using System.Linq;
using System.Collections.Generic;

record P(string Name, int Age);
var people = new List<P> { new("Bo", 30), new("Ana", 30), new("Cy", 22) };
var ordered = people.OrderBy(p => p.Age).ThenBy(p => p.Name);
foreach (var p in ordered) Console.WriteLine($"{p.Age} {p.Name}");

为什么不使用第二个 OrderBy

调用两次 OrderBy 并不能提供平局决胜条件——第二次调用会重新进行完整排序,并丢弃第一次排序的结果。

进行分层排序时,请始终在最初的 OrderBy 后使用 ThenBy。

using System;
using System.Linq;
using System.Collections.Generic;

record P(string N, int A);
var ps = new List<P> { new("Bo", 30), new("Ana", 30) };
var wrong = ps.OrderBy(p => p.A).OrderBy(p => p.N);
foreach (var p in wrong) Console.WriteLine(p.N);

查询语法中的排序子句

查询语法包含 orderby 子句。您可以用逗号分隔多个键,也可以选择使用 descending。

orderby p.Age, p.Name descending 会先按年龄排序;年龄相同时,再按姓名倒序排序。

using System;
using System.Linq;
using System.Collections.Generic;

record P(string N, int A);
var ps = new List<P> { new("Bo", 30), new("Ana", 30), new("Cy", 22) };
var q = from p in ps orderby p.A, p.N select p.N;
Console.WriteLine(string.Join(", ", q));

使用 GroupBy 分组

GroupBy 会根据键将序列划分为多个组。它返回一个由 IGrouping<TKey, TElement> 构成的序列。

每个分组都会公开自己的 Key,并且本身可以迭代其中的元素。

using System;
using System.Linq;

int[] nums = { 1, 2, 3, 4, 5, 6 };
var groups = nums.GroupBy(n => n % 2 == 0 ? "even" : "odd");
foreach (var g in groups)
  Console.WriteLine($"{g.Key}: {string.Join(\",\", g)}");

分组键和成员

每个分组的 Key 用于标识该分区,迭代分组时会得到其中的成员。您可以直接对分组调用 Count()。

这正是构建直方图、统计汇总和类别分布的方式。

using System;
using System.Linq;

string[] fruit = { "apple", "avocado", "banana", "cherry" };
var byLetter = fruit.GroupBy(f => f[0]);
foreach (var g in byLetter)
  Console.WriteLine($"{g.Key}: {g.Count()}");

分组后进行投影

一种常见模式是在 GroupBy 后使用 Select,将每个分组投影为汇总对象。

您可以读取 Key 并聚合成员,例如计算每个分组的数量或总和。

using System;
using System.Linq;
using System.Collections.Generic;

record Sale(string City, int Amt);
var sales = new List<Sale> { new("NY", 5), new("LA", 3), new("NY", 2) };
var totals = sales.GroupBy(s => s.City)
                  .Select(g => new { g.Key, Sum = g.Sum(x => x.Amt) });
foreach (var t in totals) Console.WriteLine($"{t.Key}={t.Sum}");

使用元素选择器进行 GroupBy

GroupBy 有一个重载,可以接收第二个 λ 表达式,即元素选择器。它决定每个分组存储的内容,而不仅仅是决定分组键。

这里我们按城市分组,但只存储金额。

using System;
using System.Linq;
using System.Collections.Generic;

record Sale(string City, int Amt);
var sales = new List<Sale> { new("NY", 5), new("NY", 2) };
var g = sales.GroupBy(s => s.City, s => s.Amt);
foreach (var grp in g)
  Console.WriteLine($"{grp.Key}: {string.Join(\",\", grp)}");

排序和分组都是延迟执行的

OrderBy 和 GroupBy 都采用延迟执行——只有在枚举时才会运行。但请注意,排序和分组必须读取完整个源序列,才能产生第一个元素。

因此,与 Where 不同,它们不是流式处理;相关开销会在第一次迭代时产生。

using System;
using System.Linq;

int[] nums = { 3, 1, 2 };
var q = nums.OrderBy(n => n);
Console.WriteLine("Query built");
Console.WriteLine(string.Join(", ", q));

快速检查

想一想多级排序。

总结

OrderBy/OrderByDescending 按键排序;ThenBy 添加平局决胜条件。第二个 OrderBy 会重新排序,而不是提供平局决胜条件。

GroupBy 会将元素划分为带有 Key 和成员的 IGrouping 对象,这些对象通常还会被投影为汇总结果。两者都是延迟执行的,但都会读取完整个源序列。接下来我们将进行聚合和物化。

常见问题解答

「OrderBy 与分组」课时是免费的吗?

是的 — 「OrderBy 与分组」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。

「OrderBy 与分组」这节课中我会学到什么?

对结果排序并分组 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「OrderBy 与分组」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. WHERE 与筛选
  2. SELECT 与投影
  3. OrderBy 与分组
  4. 聚合与 ToList
← 返回 C# Academy