LINQ

[C#/LINQ] GroupByメソッドの使い方 – 要素をグループ化する

C#のLINQにおけるGroupByメソッドは、コレクション内の要素を指定したキーに基づいてグループ化するために使用されます。

GroupByは、各要素に対してキーを生成し、そのキーに基づいて要素をグループに分けます。

結果はIEnumerable<IGrouping<TKey, TElement>>型で返され、各グループはキーとそのキーに関連する要素のコレクションを持ちます。

例えば、リスト内のオブジェクトを特定のプロパティでグループ化する際に便利です。

GroupByメソッドとは

C#のLINQ(Language Integrated Query)におけるGroupByメソッドは、コレクション内の要素を特定のキーに基づいてグループ化するための強力な機能です。

このメソッドを使用することで、データを整理し、特定の条件に基づいて集計や分析を行うことが容易になります。

例えば、顧客データを地域ごとにグループ化したり、売上データを商品カテゴリごとにまとめたりすることが可能です。

GroupByメソッドは、LINQのクエリ構文やメソッド構文の両方で使用でき、結果はIEnumerable<T>型のコレクションとして返されます。

これにより、グループ化されたデータに対してさらに操作を行うことができ、柔軟なデータ処理が実現します。

特に、データ分析やレポート作成において非常に役立つ機能です。

GroupByメソッドの基本的な使い方

単純なグループ化の例

GroupByメソッドを使用して、単純なデータのグループ化を行う基本的な例を示します。

以下のコードでは、整数のリストを偶数と奇数にグループ化しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        
        var groupedNumbers = numbers.GroupBy(n => n % 2 == 0 ? "偶数" : "奇数");
        
        foreach (var group in groupedNumbers)
        {
            Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
        }
    }
}
奇数: 1, 3, 5, 7, 9
偶数: 2, 4, 6, 8, 10

この例では、整数のリストを偶数と奇数に分けて表示しています。

GroupByメソッドの引数には、グループ化の基準となる条件を指定しています。

匿名型を使ったグループ化

次に、匿名型を使用してオブジェクトのリストをグループ化する例を示します。

以下のコードでは、学生の成績データを科目ごとにグループ化しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 }
        };
        
        var groupedStudents = students.GroupBy(s => s.Subject);
        
        foreach (var group in groupedStudents)
        {
            Console.WriteLine($"{group.Key}: {string.Join(", ", group.Select(s => s.Name))}");
        }
    }
}
数学: 田中, 佐藤
英語: 鈴木, 高橋

この例では、学生の成績を科目ごとにグループ化し、各科目に属する学生の名前を表示しています。

グループ化後のデータの操作

GroupByメソッドを使用した後、グループ化されたデータに対してさまざまな操作を行うことができます。

以下の例では、各グループの平均スコアを計算しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 }
        };
        
        var averageScores = students.GroupBy(s => s.Subject)
                                    .Select(g => new
                                    {
                                        Subject = g.Key,
                                        AverageScore = g.Average(s => s.Score)
                                    });
        
        foreach (var avg in averageScores)
        {
            Console.WriteLine($"{avg.Subject}の平均スコア: {avg.AverageScore}");
        }
    }
}
数学の平均スコア: 87.5
英語の平均スコア: 83

この例では、各科目ごとの平均スコアを計算し、表示しています。

キーのカスタマイズ方法

GroupByメソッドでは、グループ化のキーをカスタマイズすることも可能です。

以下の例では、学生の成績を科目とスコアの範囲でグループ化しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 }
        };
        
        var groupedByScoreRange = students.GroupBy(s => s.Score >= 85 ? "高得点" : "低得点");
        
        foreach (var group in groupedByScoreRange)
        {
            Console.WriteLine($"{group.Key}: {string.Join(", ", group.Select(s => s.Name))}");
        }
    }
}
高得点: 田中, 佐藤, 高橋
低得点: 鈴木

この例では、スコアが85以上の学生を「高得点」とし、それ未満の学生を「低得点」としてグループ化しています。

これにより、条件に応じた柔軟なグループ化が可能になります。

GroupByメソッドの応用

複数のキーを使ったグループ化

GroupByメソッドでは、複数のキーを使用してデータをグループ化することも可能です。

以下の例では、学生の成績データを科目とスコアの範囲でグループ化しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var groupedStudents = students.GroupBy(s => new { s.Subject, ScoreRange = s.Score >= 85 ? "高得点" : "低得点" });
        
        foreach (var group in groupedStudents)
        {
            Console.WriteLine($"{group.Key.Subject} - {group.Key.ScoreRange}: {string.Join(", ", group.Select(s => s.Name))}");
        }
    }
}
数学 - 高得点: 田中, 佐藤
数学 - 低得点: 山田
英語 - 高得点: 高橋
英語 - 低得点: 鈴木

この例では、科目ごとにスコアの範囲でグループ化し、各グループの学生の名前を表示しています。

グループごとの集計処理

GroupByメソッドを使用して、グループごとの集計処理を行うことができます。

以下の例では、各科目ごとの学生数をカウントしています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var studentCountBySubject = students.GroupBy(s => s.Subject)
                                             .Select(g => new
                                             {
                                                 Subject = g.Key,
                                                 Count = g.Count()
                                             });
        
        foreach (var subject in studentCountBySubject)
        {
            Console.WriteLine($"{subject.Subject}の学生数: {subject.Count}");
        }
    }
}
数学の学生数: 3
英語の学生数: 2

この例では、各科目ごとの学生数をカウントし、表示しています。

グループ化後にソートを行う方法

GroupByメソッドを使用した後、グループ化されたデータをソートすることも可能です。

以下の例では、科目ごとの平均スコアを計算し、平均スコアの降順で表示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var averageScores = students.GroupBy(s => s.Subject)
                                    .Select(g => new
                                    {
                                        Subject = g.Key,
                                        AverageScore = g.Average(s => s.Score)
                                    })
                                    .OrderByDescending(g => g.AverageScore);
        
        foreach (var avg in averageScores)
        {
            Console.WriteLine($"{avg.Subject}の平均スコア: {avg.AverageScore}");
        }
    }
}
数学の平均スコア: 83.33333333333333
英語の平均スコア: 83

この例では、各科目ごとの平均スコアを計算し、平均スコアの降順で表示しています。

グループ化したデータをフラットに戻す方法

GroupByメソッドでグループ化したデータをフラットに戻すには、SelectManyメソッドを使用します。

以下の例では、グループ化された学生データをフラットなリストに戻しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var flatList = students.GroupBy(s => s.Subject)
                               .SelectMany(g => g);
        
        foreach (var student in flatList)
        {
            Console.WriteLine($"{student.Name} - {student.Subject}: {student.Score}");
        }
    }
}
田中 - 数学: 85
佐藤 - 数学: 90
鈴木 - 英語: 78
高橋 - 英語: 88
山田 - 数学: 75

この例では、グループ化された学生データをフラットなリストに戻し、各学生の名前、科目、スコアを表示しています。

これにより、元のデータ構造に戻すことができます。

GroupByメソッドのパフォーマンスと注意点

大量データに対するGroupByのパフォーマンス

GroupByメソッドは、大量のデータをグループ化する際にパフォーマンスに影響を与える可能性があります。

特に、データセットが非常に大きい場合、グループ化処理にかかる時間が増加することがあります。

これは、グループ化のために内部でハッシュテーブルを使用するためです。

ハッシュテーブルのサイズが大きくなると、メモリの使用量も増加し、パフォーマンスが低下することがあります。

パフォーマンスを最適化するためには、以下の点に注意することが重要です。

  • グループ化するデータのサイズを可能な限り小さくする。
  • 必要なデータのみを事前にフィルタリングする。
  • グループ化のキーを適切に選定し、計算コストを最小限に抑える。

GroupByのメモリ使用量に関する注意点

GroupByメソッドを使用すると、グループ化されたデータを保持するためにメモリが消費されます。

特に、グループ数が多い場合や、各グループに多くの要素が含まれる場合、メモリ使用量が急増することがあります。

これにより、アプリケーションのパフォーマンスが低下したり、メモリ不足のエラーが発生する可能性があります。

メモリ使用量を抑えるためには、以下の方法が考えられます。

  • 不要なデータをグループ化する前にフィルタリングする。
  • グループ化の結果を必要な範囲でのみ使用し、不要なデータは早めに解放する。
  • 大量のデータを扱う場合は、ストリーミング処理を検討する。

遅延実行とGroupByの関係

LINQの特徴の一つに、遅延実行があります。

GroupByメソッドもこの遅延実行の特性を持っており、実際にデータを列挙するまでグループ化処理は実行されません。

これにより、必要なデータのみを処理することができ、パフォーマンスの向上が期待できます。

遅延実行の利点を活かすためには、以下の点に注意が必要です。

  • グループ化の結果をすぐに使用する場合は、ToList()やToArray()メソッドを使用して即座に評価する。
  • グループ化の結果を複数回使用する場合は、結果をキャッシュして再利用する。

GroupByとIEqualityComparerのカスタマイズ

GroupByメソッドでは、デフォルトのキー比較を使用しますが、IEqualityComparerをカスタマイズすることで、独自の比較ロジックを実装することができます。

これにより、特定の条件に基づいてグループ化を行うことが可能になります。

例えば、文字列の大文字小文字を無視してグループ化する場合などです。

以下は、IEqualityComparerをカスタマイズしてGroupByメソッドを使用する例です。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
}
class CaseInsensitiveComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return string.Equals(x, y, StringComparison.OrdinalIgnoreCase);
    }
    public int GetHashCode(string obj)
    {
        return obj.ToLower().GetHashCode();
    }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学" },
            new Student { Name = "佐藤", Subject = "数学" },
            new Student { Name = "鈴木", Subject = "英語" },
            new Student { Name = "高橋", Subject = "英語" },
            new Student { Name = "山田", Subject = "数学" }
        };
        
        var groupedStudents = students.GroupBy(s => s.Subject, new CaseInsensitiveComparer());
        
        foreach (var group in groupedStudents)
        {
            Console.WriteLine($"{group.Key}: {string.Join(", ", group.Select(s => s.Name))}");
        }
    }
}
数学: 田中, 佐藤, 山田
英語: 鈴木, 高橋

この例では、IEqualityComparerをカスタマイズして、科目名の大文字小文字を無視してグループ化しています。

これにより、より柔軟なグループ化が可能になります。

GroupByメソッドの具体例

数値データをグループ化する例

数値データをグループ化する基本的な例として、整数のリストを偶数と奇数に分ける方法を示します。

以下のコードでは、数値をグループ化し、それぞれのグループの内容を表示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        
        var groupedNumbers = numbers.GroupBy(n => n % 2 == 0 ? "偶数" : "奇数");
        
        foreach (var group in groupedNumbers)
        {
            Console.WriteLine($"{group.Key}: {string.Join(", ", group)}");
        }
    }
}
奇数: 1, 3, 5, 7, 9
偶数: 2, 4, 6, 8, 10

この例では、整数のリストを偶数と奇数に分けて表示しています。

文字列データをグループ化する例

次に、文字列データをグループ化する例を示します。

以下のコードでは、果物のリストをその種類ごとにグループ化しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        List<string> fruits = new List<string> { "リンゴ", "バナナ", "オレンジ", "リンゴ", "バナナ", "グレープ" };
        
        var groupedFruits = fruits.GroupBy(f => f);
        
        foreach (var group in groupedFruits)
        {
            Console.WriteLine($"{group.Key}: {group.Count()}個");
        }
    }
}
リンゴ: 2個
バナナ: 2個
オレンジ: 1個
グレープ: 1個

この例では、果物のリストを種類ごとにグループ化し、各種類の個数を表示しています。

オブジェクトのプロパティを使ったグループ化

オブジェクトのプロパティを使用してグループ化する例として、学生の成績データを科目ごとにグループ化する方法を示します。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 }
        };
        
        var groupedStudents = students.GroupBy(s => s.Subject);
        
        foreach (var group in groupedStudents)
        {
            Console.WriteLine($"{group.Key}: {string.Join(", ", group.Select(s => s.Name))}");
        }
    }
}
数学: 田中, 佐藤
英語: 鈴木, 高橋

この例では、学生の成績を科目ごとにグループ化し、各科目に属する学生の名前を表示しています。

日付データを使ったグループ化

日付データを使ったグループ化の例として、日付ごとの売上データをグループ化する方法を示します。

以下のコードでは、売上データを日付ごとに集計しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Sale
{
    public DateTime Date { get; set; }
    public decimal Amount { get; set; }
}
class Program
{
    static void Main()
    {
        List<Sale> sales = new List<Sale>
        {
            new Sale { Date = new DateTime(2023, 10, 1), Amount = 1000 },
            new Sale { Date = new DateTime(2023, 10, 1), Amount = 1500 },
            new Sale { Date = new DateTime(2023, 10, 2), Amount = 2000 },
            new Sale { Date = new DateTime(2023, 10, 2), Amount = 2500 },
            new Sale { Date = new DateTime(2023, 10, 3), Amount = 3000 }
        };
        
        var groupedSales = sales.GroupBy(s => s.Date.Date)
                                .Select(g => new
                                {
                                    Date = g.Key,
                                    TotalAmount = g.Sum(s => s.Amount)
                                });
        
        foreach (var group in groupedSales)
        {
            Console.WriteLine($"{group.Date.ToShortDateString()} の売上合計: {group.TotalAmount}円");
        }
    }
}
2023/10/01 の売上合計: 2500円
2023/10/02 の売上合計: 4500円
2023/10/03 の売上合計: 3000円

この例では、売上データを日付ごとにグループ化し、各日付の売上合計を表示しています。

これにより、日付ごとの売上の傾向を把握することができます。

GroupByメソッドの応用例

グループごとの最大値・最小値を取得する

GroupByメソッドを使用して、グループごとの最大値や最小値を取得することができます。

以下の例では、学生の成績データを科目ごとにグループ化し、各科目の最高得点と最低得点を表示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var scoreStats = students.GroupBy(s => s.Subject)
                                 .Select(g => new
                                 {
                                     Subject = g.Key,
                                     MaxScore = g.Max(s => s.Score),
                                     MinScore = g.Min(s => s.Score)
                                 });
        
        foreach (var stat in scoreStats)
        {
            Console.WriteLine($"{stat.Subject} - 最大得点: {stat.MaxScore}, 最小得点: {stat.MinScore}");
        }
    }
}
数学 - 最大得点: 90, 最小得点: 75
英語 - 最大得点: 88, 最小得点: 78

この例では、各科目ごとの最高得点と最低得点を計算し、表示しています。

グループごとの平均値を計算する

次に、グループごとの平均値を計算する例を示します。

以下のコードでは、学生の成績データを科目ごとにグループ化し、各科目の平均得点を表示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var averageScores = students.GroupBy(s => s.Subject)
                                    .Select(g => new
                                    {
                                        Subject = g.Key,
                                        AverageScore = g.Average(s => s.Score)
                                    });
        
        foreach (var avg in averageScores)
        {
            Console.WriteLine($"{avg.Subject}の平均得点: {avg.AverageScore}");
        }
    }
}
数学の平均得点: 83.33333333333333
英語の平均得点: 83

この例では、各科目ごとの平均得点を計算し、表示しています。

グループごとのカウントを取得する

GroupByメソッドを使用して、グループごとの要素数をカウントすることもできます。

以下の例では、学生の成績データを科目ごとにグループ化し、各科目の学生数を表示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var studentCountBySubject = students.GroupBy(s => s.Subject)
                                             .Select(g => new
                                             {
                                                 Subject = g.Key,
                                                 Count = g.Count()
                                             });
        
        foreach (var subject in studentCountBySubject)
        {
            Console.WriteLine($"{subject.Subject}の学生数: {subject.Count}");
        }
    }
}
数学の学生数: 3
英語の学生数: 2

この例では、各科目ごとの学生数をカウントし、表示しています。

グループごとの最初の要素・最後の要素を取得する

GroupByメソッドを使用して、グループごとの最初の要素や最後の要素を取得することもできます。

以下の例では、学生の成績データを科目ごとにグループ化し、各科目の最初の学生と最後の学生を表示しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var firstLastStudents = students.GroupBy(s => s.Subject)
                                        .Select(g => new
                                        {
                                            Subject = g.Key,
                                            FirstStudent = g.First(),
                                            LastStudent = g.Last()
                                        });
        
        foreach (var group in firstLastStudents)
        {
            Console.WriteLine($"{group.Subject} - 最初の学生: {group.FirstStudent.Name}, 最後の学生: {group.LastStudent.Name}");
        }
    }
}
数学 - 最初の学生: 田中, 最後の学生: 75
英語 - 最初の学生: 鈴木, 最後の学生: 高橋

この例では、各科目ごとの最初の学生と最後の学生を表示しています。

グループごとのサブグループ化

GroupByメソッドを使用して、グループ内でさらにサブグループ化することも可能です。

以下の例では、学生の成績データを科目ごとにグループ化し、さらに得点の範囲でサブグループ化しています。

using System;
using System.Collections.Generic;
using System.Linq;
class Student
{
    public string Name { get; set; }
    public string Subject { get; set; }
    public int Score { get; set; }
}
class Program
{
    static void Main()
    {
        List<Student> students = new List<Student>
        {
            new Student { Name = "田中", Subject = "数学", Score = 85 },
            new Student { Name = "佐藤", Subject = "数学", Score = 90 },
            new Student { Name = "鈴木", Subject = "英語", Score = 78 },
            new Student { Name = "高橋", Subject = "英語", Score = 88 },
            new Student { Name = "山田", Subject = "数学", Score = 75 }
        };
        
        var subGroupedStudents = students.GroupBy(s => s.Subject)
                                         .Select(g => new
                                         {
                                             Subject = g.Key,
                                             ScoreGroups = g.GroupBy(s => s.Score >= 85 ? "高得点" : "低得点")
                                         });
        
        foreach (var group in subGroupedStudents)
        {
            Console.WriteLine($"{group.Subject}:");
            foreach (var scoreGroup in group.ScoreGroups)
            {
                Console.WriteLine($"  {scoreGroup.Key}: {string.Join(", ", scoreGroup.Select(s => s.Name))}");
            }
        }
    }
}
数学:
  高得点: 田中, 佐藤
  低得点: 山田
英語:
  高得点: 高橋
  低得点: 鈴木

この例では、科目ごとにグループ化した後、得点の範囲でサブグループ化し、各グループの学生の名前を表示しています。

これにより、より詳細なデータ分析が可能になります。

まとめ

この記事では、C#のLINQにおけるGroupByメソッドの基本的な使い方から応用例までを詳しく解説しました。

特に、グループ化の方法や、グループごとの集計処理、サブグループ化のテクニックについて具体的なコード例を通じて説明しました。

これを機に、実際のプロジェクトでGroupByメソッドを活用し、データの整理や分析を効率的に行ってみてください。

関連記事

Back to top button