0Pricing
C# Academy · Урок

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 — локальная установка не требуется.

Все уроки этого курса

  1. WHERE и фильтрация
  2. SELECT и проекция
  3. OrderBy и группировка
  4. Агрегаты и ToList
← Назад к C# Academy