ストップforeach!LINQで集合結合する
C#
1. はじめに
2年間C#プロジェクトに携わった中でよく使ってきたLINQまとめ に引き続きLINQ記事です。 LINQを知らないと、コレクションを扱う際に、ついforeachを使ってしまうかと思います。 そのforeach、ちょっと待ってください!!! LINQを使って簡単に集合・結合操作が行えるのでまとめていきたいと思います。
2. 集合
2-1. Union (和集合)
コレクション同士を連結します。 重複するデータがある場合は1件のみに絞られます。
var listA = new string[] { "りんご", "ばなな", "ぶどう", "みかん" };
var listB = new string[] { "さくらんぼ", "ばなな", "もも", "りんご" };
var list = listA.Union(listB);
foreach (var item in list)
{
System.Console.WriteLine(item);
}
<結果>
2-2. Concat (和集合)
コレクション同士を連結します。 重複するデータがある場合はそのまま連結されます。(Union Allのイメージです。)
void Main()
{
var listA = new string[] { "りんご", "ばなな", "ぶどう", "みかん" };
var listB = new string[] { "さくらんぼ", "ばなな", "もも", "りんご" };
var list = listA.Concat(listB);
foreach (var item in list)
{
System.Console.WriteLine(item);
}
}
<結果>
2-3. Intersect (積集合)
2つのコレクションのどちらにも含まれている要素のみ抽出します。
var listA = new string[] { "りんご", "ばなな", "ぶどう", "みかん" };
var listB = new string[] { "さくらんぼ", "ばなな", "もも", "りんご" };
var list = listA.Intersect(listB);
foreach (var item in list)
{
System.Console.WriteLine(item);
}
<結果>
2-4. Except (差集合)
左側のコレクション要素から、右側のコレクション要素を引きます。
var listA = new string[] { "りんご", "ばなな", "ぶどう", "みかん" };
var listB = new string[] { "さくらんぼ", "ばなな", "もも", "りんご" };
var list = listA.Except(listB);
foreach (var item in list)
{
System.Console.WriteLine(item);
}
<結果>
3. 結合
3-1. Join (内部結合)
指定したキーに基づいて、コレクションを内部結合します。 以下の例では「社員.部署ID」と「部署.部署ID」をキーとして結合し、 1つのコレクションを作成しています。
// 従業員
public class Employee
{
// 従業員ID
public int Id { get; set;}
// 部署ID
public int DepartmentId { get; set;}
// 従業員名
public string Name { get; set;}
}
// 部署
public class Department
{
// 部署ID
public int Id { get; set;}
// 部署名
public string Name { get; set;}
}
// 従業員データ
var employeeList = new List<Employee>
{
new Employee { Id = 100, Name = "佐藤", DepartmentId = 1 },
new Employee { Id = 101, Name = "鈴木", DepartmentId = 2 },
new Employee { Id = 102, Name = "高橋", DepartmentId = 3 },
new Employee { Id = 103, Name = "田中", DepartmentId = 2 },
new Employee { Id = 104, Name = "伊藤", DepartmentId = 1 },
new Employee { Id = 105, Name = "渡辺", DepartmentId = 3 },
new Employee { Id = 106, Name = "山本", DepartmentId = 1 },
};
// 部署データ
var departmentList = new List<Department>
{
new Department { Id = 1, Name = "開発部" },
new Department { Id = 2, Name = "研究部" },
new Department { Id = 3, Name = "総務部" }
};
var list = employeeList.Join(departmentList, e => e.DepartmentId, d => d.Id, (e, d) => new
{
EmployeeId = e.Id,
EmployeeName = e.Name,
DepartmentName = d.Name
});
foreach (var item in list)
{
System.Console.WriteLine(item);
}
<結果>
3-2. GroupJoin (外部結合)
指定したキーに基づいて、コレクションを外部結合します。 以下の例では、「社員.部署ID」と「部署.部署ID」をキーとして結合しますが、 紐づくキーがない場合は部署にnullを設定するようにしています。
// 従業員
public class Employee
{
// 従業員ID
public int Id { get; set;}
// 部署ID(null許容型)
public int? DepartmentId { get; set;}
// 従業員名
public string Name { get; set;}
}
// 部署
public class Department
{
// 部署ID
public int Id { get; set;}
// 部署名
public string Name { get; set;}
}
void Main()
{
// 従業員データ
var employeeList = new List<Employee>
{
new Employee { Id = 100, Name = "佐藤", DepartmentId = 1 },
new Employee { Id = 101, Name = "鈴木", DepartmentId = 2 },
new Employee { Id = 102, Name = "高橋", DepartmentId = null },
new Employee { Id = 103, Name = "田中", DepartmentId = null },
new Employee { Id = 104, Name = "伊藤", DepartmentId = 1 },
new Employee { Id = 105, Name = "渡辺", DepartmentId = 3 },
new Employee { Id = 106, Name = "山本", DepartmentId = 1 },
};
// 部署データ
var departmentList = new List<Department>
{
new Department { Id = 1, Name = "開発部" },
new Department { Id = 2, Name = "研究部" },
new Department { Id = 3, Name = "総務部" }
};
var list = employeeList.GroupJoin(departmentList, e => e.DepartmentId, d => d.Id, (e, d) => new
{
EmployeeId = e.Id,
EmployeeName = e.Name,
Departments = d.DefaultIfEmpty()
})
.SelectMany(d => d.Departments, (e, d) => new
{
EmployeeId = e.EmployeeId,
EmployeeName = e.EmployeeName,
DepartmentName = d != null ? d.Name : "所属なし"
});
foreach (var item in list)
{
System.Console.WriteLine(item);
}
}
<結果>
4. おわりに
コレクション操作はいろんな場面で使えるので、覚えておくととても便利ですね! 他にもありましたら随時更新させて頂きます。