OrderByとグループ化
結果を並べ替えてグループ化します。
「OrderByとグループ化」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これは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 は、選択したキーを基準に大きいものから小さいものへ並べ替えます。
昇順で並べ替えてから反転するのではなく、こちらを直接使ってください。意図が明確に伝わり、1回の処理で並べ替えられます。
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) は、人を年齢の若い順に並べ替えます。
キーには、数値、文字列、日付などの比較可能な型や、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による第2キーの並べ替え
ThenByは同順位を解消する条件を追加します。OrderByの後に使用すると、主キーが同じ要素を第2キーで並べ替えます。
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}");2回目のOrderByではいけない理由
OrderByを2回呼び出しても同順位を解消する条件にはなりません。2回目の呼び出しで全体が再度並べ替えられ、最初の順序は破棄されます。
段階的に並べ替える場合は、最初の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
クエリ構文には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には2つ目のラムダ式を受け取るオーバーロードがあります。これは要素セレクターと呼ばれ、グループ化のキーだけでなく、各グループに格納する内容も射影します。
ここでは都市でグループ化し、金額だけを格納します。
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は同順位を解消する条件を追加します。2回目のOrderByは全体を再度並べ替えるため、同順位を解消する条件にはなりません。
GroupByは、Keyとメンバーを持つIGroupingオブジェクトに分割し、それらを集計結果に射影することがよくあります。どちらも遅延実行されますが、入力元全体を読み取ります。次は集計とマテリアライズを学びます。
よくある質問
「OrderByとグループ化」レッスンは無料ですか?
はい。「OrderByとグループ化」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「OrderByとグループ化」で何を学びますか?
結果を並べ替えてグループ化します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「OrderByとグループ化」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Whereとフィルタリング
- SelectとProjection
- OrderByとグループ化
- 集計とToList