OrderBy и группировка
Сортируйте и группируйте результаты
«OrderBy и группировка» — бесплатный урок C# Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.
Сортировка с помощью OrderBy
OrderBy сортирует последовательность по возрастанию по выбранному ключу. Лямбда-выражение возвращает значение, по которому выполняется сортировка.
Оператор возвращает новую отсортированную последовательность и является стабильным: элементы с одинаковыми ключами сохраняют исходный взаимный порядок.
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 не добавляет дополнительный критерий: второй вызов полностью выполняет сортировку заново и отменяет первый порядок.
При многоуровневой сортировке всегда используйте ThenBy после исходного OrderBy.
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 разбивает данные на объекты IGrouping с Key и элементами, которые часто преобразуют в сводные данные. Оба оператора выполняются отложенно, но обрабатывают весь источник. Далее мы рассмотрим агрегирование и материализацию.
Часто задаваемые вопросы
Урок «OrderBy и группировка» бесплатный?
Да — полный текст урока «OrderBy и группировка» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.
Чему я научусь в уроке «OrderBy и группировка»?
Сортируйте и группируйте результаты Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «OrderBy и группировка»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- WHERE и фильтрация
- SELECT и проекция
- OrderBy и группировка
- Агрегаты и ToList