LINQとは?

LINQとは、Language Integrated Queryの略で「リンク」と読みます。

コレクションなどのデータの集まりに対して、SQLのようにデータを問い合わせる機能を

C#言語内で統一的に使用できるようにした物です。

LINQを使うと、コレクションから特定のデータを選択したり、抽出したり、並び替えたり、

などの操作を簡潔に記述できます。

参考データ

以下の様な学校の生徒と科目別成績を表すクラスを用意しました。

/// <summary>
/// 生徒
/// </summary>
private class Student
{
    public int StudentId;
    public string Name;
}

/// <summary>
/// 成績
/// </summary>
public class SubjectScore
{
    public int StudentId;
    public string Subject;
    public int Score;
}

以下の様な仮データを作ったとします。

var students = new[]
{
    new Student { StudentId = 1, Name = "山田" },
    new Student { StudentId = 2, Name = "田中" },
    new Student { StudentId = 3, Name = "佐藤" }
};

var scores = new[]
{
    new SubjectScore { StudentId = 1, Subject = "国語", Score = 80 },
    new SubjectScore { StudentId = 1, Subject = "数学", Score = 90 },
    new SubjectScore { StudentId = 2, Subject = "国語", Score = 70 },
    new SubjectScore { StudentId = 2, Subject = "数学", Score = 85 },
    new SubjectScore { StudentId = 3, Subject = "国語", Score = 75 },
    new SubjectScore { StudentId = 3, Subject = "数学", Score = 95 }
};

表にすると、以下の様に二つの表があることになります。

結合

Join:二つのコレクションを結合します

studentsscoresの二つのコレクションに対して、何を基準に結合するかと

どのデータを使用するかを指定します。

今回基準にしているのは、StudentIdで、

生徒の名前、科目、科目の成績を結合しています。

var studentScores = students.Join(
    scores,
    student => student.StudentId,
    score => score.StudentId,
    (student, score) => new { student.Name, score.Subject, score.Score }
);

foreach (var entry in studentScores)
{
    Debug.Log($"{entry.Name} - {entry.Subject}: {entry.Score}");
}

結果のログは以下の様になります。

GroupJoin:グループ化された結合状態にする

Join同様、結合の基準になる要素を指定します。

Joinでは、↑の例だと(生徒の名前、科目、科目の成績)で結合されたデータが1行ずつ作成されましたが、

GroupJoinの場合は、

(生徒、(1個以上の科目別成績))という形でグループ化された状態で結合されます。

var studentScores = students.GroupJoin(
    scores,
    student => student.StudentId,
    score => score.StudentId,
    (student, score) => new { student.Name, Scores = score }
);

foreach (var entry in studentScores)
{
    Debug.Log(entry.Name);
    foreach (var score in entry.Scores)
    {
        Debug.Log($"  {score.Subject}: {score.Score}");
    }
}

結果のログは以下の様になります。

グループ化

GroupBy:指定されたキーに基づいてデータをグループ化します

生徒の成績を表す以下のクラスがあったとします。

private class StudentScore
{
    public int StudentId;
    public string Name;
    public string Subject;
    public int Score;
}

以下のように初期化しました。

丁度表計算のシートのようになっていますね。

StudentScore[] studentScores = new[]
{
    new StudentScore { StudentId = 1, Name = "山田", Subject = "国語", Score = 80 },
    new StudentScore { StudentId = 1, Name = "山田", Subject = "数学", Score = 90 },
    new StudentScore { StudentId = 2, Name = "田中", Subject = "国語", Score = 70 },
    new StudentScore { StudentId = 2, Name = "田中", Subject = "数学", Score = 85 },
    new StudentScore { StudentId = 3, Name = "佐藤", Subject = "国語", Score = 75 },
    new StudentScore { StudentId = 3, Name = "佐藤", Subject = "数学", Score = 95 }
};

これをGroupByでグループ化します。

今回は、Subject(科目)毎にグループ化してみました。

var scoresBySubject = studentScores.GroupBy(
    studentScore => studentScore.Subject
);

foreach (var entry in scoresBySubject)
{
		Debug.Log(entry.Key);
    foreach (var score in entry)
    {
        Debug.Log($"  {score.Name} - {score.Score}");
    }
}

結果のログは以下の様になります。

まとめ

今回は、LINQによる結合とグループ化について解説しました。

うまく使えば、複雑なデータの関連付け、分類を簡潔に記述することが出来、

データの構造が分かりやすくなったり、可読性の高いコードがかけるようになります。

データの検索や集計が多い場合、非常に有用です。

機会があれば活用してみてください。

🔗関連ページ