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