C#のLINQでGroupByをマスター!データのグループ化と集計を初心者向けに徹底解説
生徒
「先生、たくさんのデータの中から『同じ種類のもの』ごとにまとめて、その合計や個数を調べたいときはどうすればいいですか?」
先生
「そんなときは、C#のLINQにある『GroupBy(グループバイ)』という機能を使うと、まるでお店で商品をカテゴリーごとに仕分けるように、簡単にデータをまとめることができますよ。」
生徒
「GroupByを使えば、例えば果物のリストからリンゴが何個あるか、合計いくらか、といった計算もすぐできるんですね!」
先生
「その通りです。データの集計はプログラミングで非常によく使う技術です。それでは、具体的な使い方を一緒に学んでいきましょう!」
1. LINQのGroupBy(グループバイ)とは?
C#のプログラミングにおいて、膨大なデータの中から特定の条件で仲間分けをしたい場面が多々あります。 例えば、学校のテスト結果から「クラスごと」に平均点を出したり、売上データから「商品カテゴリーごと」に合計金額を計算したりする場合です。
GroupBy(グループバイ)は、その名の通り「グループごとに(By)分ける(Group)」ための機能です。 これは、.NETフレームワークが提供するLINQ(リンク)という便利な道具箱の中に入っている機能の一つです。
イメージとしては、バラバラに置かれた色とりどりのボールを、赤色の箱、青色の箱、黄色の箱というように、色という「共通の特徴(キー)」を基準に仕分ける作業だと考えてください。
2. グループ化の仕組みを身近な例で考えよう
パソコンを触ったことがない方でもイメージしやすいように、スーパーマーケットのレジ袋の中身を整理する場面を想像してみましょう。
- 元のデータ:リンゴ、牛乳、バナナ、卵、ヨーグルト、オレンジ(バラバラの状態)
- 仕分けのルール(キー):「果物」か「乳製品」か
- グループ化した結果:
- 【果物グループ】:リンゴ、バナナ、オレンジ
- 【乳製品グループ】:牛乳、卵、ヨーグルト
このように、何か共通の項目を見つけて、それを基準にデータを束ねるのがGroupByの役割です。プログラミング用語では、この仕分けの基準となる項目のことを「Key(キー)」と呼びます。
3. GroupByの基本的な書き方
まずは、一番シンプルな形を見てみましょう。C#では「リスト(データの集まり)」に対して、ドット(.)でつなげてGroupByを呼び出します。
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
// 1. 元となるデータの作成(果物の名前のリスト)
List<string> fruits = new List<string> { "リンゴ", "バナナ", "リンゴ", "イチゴ", "バナナ", "リンゴ" };
// 2. GroupByを使って名前ごとにグループ化
var groupedFruits = fruits.GroupBy(f => f);
// 3. 結果を表示
foreach (var group in groupedFruits)
{
// group.Key には「リンゴ」や「バナナ」といった種類が入ります
Console.WriteLine($"種類: {group.Key} - 個数: {group.Count()}個");
}
}
}
実行結果は以下のようになります。
種類: リンゴ - 個数: 3個
種類: バナナ - 個数: 2個
種類: イチゴ - 個数: 1個
このコードの中に出てくる f => f という書き方は、ラムダ式と呼ばれるもので、「リストの中の一つひとつの要素そのものを、グループ分けの基準(キー)にしますよ」という意味です。
4. 少し高度な集計!クラスを使ったグループ化
実際の開発では、単なる文字列だけでなく、複数の情報を持った「データ(オブジェクト)」を扱うことがほとんどです。 ここでは「商品名」と「カテゴリー」、「価格」を持った商品のリストをグループ化してみましょう。
using System;
using System.Linq;
using System.Collections.Generic;
// 商品を表す設計図(クラス)
public class Product
{
public string Name { get; set; } // 名前
public string Category { get; set; } // カテゴリー
public int Price { get; set; } // 価格
}
class Program
{
static void Main()
{
// 商品データの作成
List<Product> products = new List<Product>
{
new Product { Name = "キャベツ", Category = "野菜", Price = 150 },
new Product { Name = "牛乳", Category = "乳製品", Price = 200 },
new Product { Name = "レタス", Category = "野菜", Price = 120 },
new Product { Name = "チーズ", Category = "乳製品", Price = 400 },
new Product { Name = "人参", Category = "野菜", Price = 100 }
};
// カテゴリーごとにグループ化して、それぞれの合計金額を計算
var summary = products.GroupBy(p => p.Category)
.Select(g => new
{
CategoryName = g.Key, // カテゴリー名
TotalPrice = g.Sum(p => p.Price), // 合計金額
AveragePrice = g.Average(p => p.Price), // 平均金額
Count = g.Count() // 種類数
});
foreach (var item in summary)
{
Console.WriteLine($"【{item.CategoryName}】");
Console.WriteLine($" 合計金額: {item.TotalPrice}円");
Console.WriteLine($" 平均価格: {item.AveragePrice}円");
Console.WriteLine($" 登録数: {item.Count}件");
}
}
}
実行結果は以下のようになります。
【野菜】
合計金額: 370円
平均価格: 123.333333333333円
登録数: 3件
【乳製品】
合計金額: 600円
平均価格: 300円
登録数: 2件
ここで登場した Sum(合計)、Average(平均)、Count(個数)は、GroupByで分けた後のグループに対して計算を行う非常に便利な命令です。
5. 初心者が覚えておきたい重要な用語解説
プログラミングを始めたばかりだと、聞き慣れない言葉が出てきて戸惑うかもしれません。今回の内容に関連する重要な用語を噛み砕いて説明します。
Key(キー)
グループ分けの「基準」となる値のことです。上の例では「野菜」や「乳製品」といったカテゴリーの名前がこれに当たります。
IGrouping
GroupByを実行した結果返ってくる特別な形です。「キー(見出し)」と「その中身のリスト」がセットになった構造をしています。
LINQ(リンク)
Language Integrated Queryの略で、データの集合(リストなど)から必要な情報を抜き出したり、並べ替えたりするための専用の構文のことです。
集計関数
SumやCountのように、複数の数値を使って一つの結果(合計や平均など)を導き出す計算のことです。
6. なぜGroupByを使うのか?そのメリット
もしGroupByを使わずに同じことをしようとすると、とても大変です。 まず、カテゴリーの種類を自分で調べて、新しいリストを作って、一つずつ「もし野菜なら野菜用の合計変数に足す」という命令を、条件分岐(if文)などを使って書かなければなりません。
GroupByを使うメリットは以下の通りです。
- コードが短くなる: 複雑な仕分け処理をたった一行で書くことができます。
- 間違いが減る: 自分で計算の仕組みをゼロから作らなくて良いため、計算ミスやバグ(プログラムの間違い)が入り込む隙を減らせます。
- 読みやすい: 「何を基準にグループ化して、何を合計したいのか」が誰が見ても一目で分かります。
特にデータクエリ(データへの問い合わせ)において、LINQはC#の最大の特徴とも言える強力なツールです。 SQLというデータベース専用の言葉に似た感覚でデータを扱えるため、将来的にデータベースを扱う際にもこの知識がそのまま役立ちます。
7. よくある活用シーン:売上集計のシミュレーション
もう少し実戦に近い例を考えてみましょう。あるオンラインショップの注文データがあるとします。 「どのお客さんが、いくら使ったか」という顧客別の購入合計額を出してみましょう。
// 注文データ
public class Order
{
public string CustomerName { get; set; } // お客さんの名前
public int Amount { get; set; } // 購入金額
}
// データリスト
List<Order> orders = new List<Order>
{
new Order { CustomerName = "田中さん", Amount = 1500 },
new Order { CustomerName = "佐藤さん", Amount = 3000 },
new Order { CustomerName = "田中さん", Amount = 2500 },
new Order { CustomerName = "鈴木さん", Amount = 5000 },
new Order { CustomerName = "佐藤さん", Amount = 1200 }
};
// 顧客ごとにグループ化して、購入額を合計
var customerStats = orders.GroupBy(o => o.CustomerName)
.Select(group => new
{
Name = group.Key,
Total = group.Sum(o => o.Amount)
});
foreach (var stat in customerStats)
{
Console.WriteLine($"{stat.Name}様の購入合計: {stat.Total}円");
}
この例のように、大量の取引記録から「人ごと」や「月ごと」の数字を算出する処理は、ビジネスアプリ開発において必須のスキルです。 GroupByを使いこなすことで、生の状態ではただの数字の羅列だったものが、意味のある「情報」へと生まれ変わります。
8. LINQを使うための準備(初心者向け注意点)
自分でコードを書いてみる際に、一つだけ注意点があります。
LINQの機能を使うためには、プログラムの冒頭に using System.Linq; という一行を書く必要があります。
これは「LINQという道具箱を使えるように準備してください」という宣言です。これがないと、GroupByと書いても「そんな命令は知りません」とコンピュータがエラーを出してしまいます。
もしエラーが出たときは、まず一番上の using の部分を確認してみてください。
また、GroupByの結果は特殊な形式(IEnumerableの入れ子)になっているため、そのまま画面に表示することはできません。
必ず foreach という繰り返し命令を使って中身を取り出すか、Select を使って表示しやすい形に加工してあげる必要があります。
9. 集計をもっと便利にするためのテクニック
GroupByは、複数の値を組み合わせた「複合キー」でのグループ化も可能です。 例えば、「2024年の・1月の・売上」のように、年と月を組み合わせて細かく分類することもできます。
さらに、グループ化した後に OrderBy という命令を付け加えることで、「合計金額が高い順にグループを並べる」といった処理も自由自在です。
このようにLINQは、複数の命令を数珠つなぎ(メソッドチェーンと呼びます)にして、より高度なデータ加工を行えるのが魅力です。
プログラミング未経験の方は、まずは「データを共通点で見出しをつけて箱に分ける」という感覚を大切にしてください。 この感覚さえ掴めれば、GroupByの使い方は自然と身についていきます。 最初は少し難しく感じるかもしれませんが、実際にコードを書いてみて、自分の意図通りにデータがまとまる快感をぜひ体験してほしいと思います。