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:二つのコレクションを結合します
studentsとscoresの二つのコレクションに対して、何を基準に結合するかと
どのデータを使用するかを指定します。
今回基準にしているのは、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による結合とグループ化について解説しました。
うまく使えば、複雑なデータの関連付け、分類を簡潔に記述することが出来、
データの構造が分かりやすくなったり、可読性の高いコードがかけるようになります。
データの検索や集計が多い場合、非常に有用です。
機会があれば活用してみてください。