集計とToList
CountやSumを使い、リストとして具体化します。
「集計とToList」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
要素を数える
Countは、シーケンス内の要素数を返します。述語を指定すると、条件に一致する要素だけを数えます。
これは列挙を強制するため、合計を生成するまでシーケンス全体を走査します。集計操作の一種です。
using System;
using System.Linq;
int[] nums = { 1, 2, 3, 4, 5 };
Console.WriteLine(nums.Count());
Console.WriteLine(nums.Count(n => n > 2));値を合計する
Sumは数値を加算します。数値シーケンスに対して使用すると要素を合計し、セレクターを指定すると各要素から射影した値を合計します。
戻り値は、元のシーケンスまたはセレクターの結果と同じ数値型になります。
using System;
using System.Linq;
using System.Collections.Generic;
record Order(int Qty, decimal Price);
var orders = new List<Order> { new(2, 5m), new(3, 4m) };
decimal total = orders.Sum(o => o.Qty * o.Price);
Console.WriteLine(total);値の平均を求める
Averageは算術平均を計算します。Sumと同様に、オプションのセレクターを指定できます。
元のシーケンスが整数であっても、結果は浮動小数点型(たとえばdouble)になります。これにより、除算で精度が失われることを防げます。
using System;
using System.Linq;
int[] scores = { 80, 90, 100 };
double avg = scores.Average();
Console.WriteLine(avg);最小値と最大値
MinとMaxは、最小値と最大値を返します。セレクターを指定すると、射影されたキーを対象に集計します。
最新の.NETでは、MaxByとMinByを使うと、キーの値だけでなく、極端なキーを持つ要素全体が返されます。
using System;
using System.Linq;
using System.Collections.Generic;
record P(string Name, int Age);
var ps = new List<P> { new("Ana", 30), new("Bo", 22) };
var oldest = ps.MaxBy(p => p.Age);
Console.WriteLine(oldest!.Name);空のシーケンスに関する注意点
空のシーケンスに対して値型のAverage、Min、Maxを使用すると、InvalidOperationExceptionがスローされます。Sumは0を返し、Countも0を返します。
空になる可能性があるデータの平均を求める前に、Any()で確認するか、DefaultIfEmptyを使用してください。
using System;
using System.Linq;
int[] empty = Array.Empty<int>();
double avg = empty.DefaultIfEmpty(0).Average();
Console.WriteLine(avg);独自の畳み込みにAggregateを使う
Aggregateは、アキュムレーター関数を使ってシーケンスを1つの値に畳み込みます。これはSumなどの背後にある一般的な形式です。
初期値を指定し、各要素を実行中の結果に結合できます。積や連結、独自の処理などに便利です。
using System;
using System.Linq;
int[] nums = { 1, 2, 3, 4 };
int product = nums.Aggregate(1, (acc, n) => acc * n);
Console.WriteLine(product);ToListでマテリアライズする
ToListはクエリをすぐに実行し、結果をList<T>にコピーします。これにより、意図的に遅延実行を終了させます。
安定したスナップショットを取得したい場合、高コストなパイプラインの再実行を避けたい場合、インデックスやCountプロパティなど、リストの機能を使いたい場合に使用します。
using System;
using System.Linq;
int[] nums = { 1, 2, 3, 4 };
var evens = nums.Where(n => n % 2 == 0).ToList();
evens.Add(6);
Console.WriteLine(string.Join(", ", evens));ToArrayとToDictionary
関連するマテリアライザーには、固定サイズの配列を作成するToArrayと、キーによる検索を行うToDictionaryがあります。
ToDictionaryはキーセレクター(およびオプションの値セレクター)を受け取り、2つの要素が同じキーを生成するとスローします。
using System;
using System.Linq;
using System.Collections.Generic;
record P(string Name, int Age);
var ps = new List<P> { new("Ana", 30), new("Bo", 22) };
var byName = ps.ToDictionary(p => p.Name, p => p.Age);
Console.WriteLine(byName["Ana"]);マテリアライズする理由
遅延実行されるクエリは、反復処理されるたびに再実行されます。パイプラインのコストが高い場合や、変化するデータ元を読み取る場合、この繰り返しによってバグや速度低下が発生します。
ToListを1回呼び出すと結果が取得されるため、その後の読み取りは低コストで一貫したものになります。
using System;
using System.Linq;
int runs = 0;
int[] nums = { 1, 2, 3 };
var list = nums.Select(n => { runs++; return n; }).ToList();
foreach (var _ in list) { }
foreach (var _ in list) { }
Console.WriteLine(runs);First、Single、Any
要素演算子も実行を強制します。Firstは最初に一致する要素を返し、一致する要素がなければスローします。FirstOrDefaultは代わりに既定値を返し、Singleは要素がちょうど1つであることを要求します。
Anyは、すべての要素を数え上げることなく、シーケンスに一致する要素があるかどうかを示します。
using System;
using System.Linq;
int[] nums = { 3, 8, 5, 12 };
int firstBig = nums.First(n => n > 7);
bool hasOdd = nums.Any(n => n % 2 == 1);
Console.WriteLine($"{firstBig} {hasOdd}");完全なパイプライン
実際のクエリでは、フィルタリング、射影、並べ替え、集計をつなげ、最後にマテライザーを置くことがよくあります。
上から下へ、フィルター、形の整形、順序付け、収集という順に読みます。最後のToListによって、パイプライン全体が1回実行されます。
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", 9) };
var top = sales.Where(s => s.Amt > 4)
.OrderByDescending(s => s.Amt)
.Select(s => s.City)
.ToList();
Console.WriteLine(string.Join(", ", top));確認してみましょう
遅延実行とマテリアライズについて考えてみましょう。
まとめ
集計演算子はシーケンスを1つの値に縮約します。Count、Sum、Average、Min/Max、MinBy/MaxBy、そして汎用的なAggregateがあります。これらは実行を強制し、空の入力元に対してはスローすることがあります。
ToList、ToArray、ToDictionaryは結果をマテリアライズし、遅延実行を終了させます。そのため、高コストなパイプラインを1回だけ実行できます。これで、LINQのフィルタリングと射影に関するツールキットは完了です。
よくある質問
「集計とToList」レッスンは無料ですか?
はい。「集計とToList」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「集計とToList」で何を学びますか?
CountやSumを使い、リストとして具体化します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「集計とToList」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。