二つの集合の重複する部分を検出して、重複個所のファイルを削除するクエリをさっと書きたいと思った。
LINQ でできるだろうと思っていたのだけど、やり方を知らなかったので調べた。
Join
ここに書いているが、Query expression だった。普段私は Lambda expression を使うので両方で使ってみよう。変換はこちらのブログ
が参考になりそうだが、残念ながら、複数のキーでのJoinに関しては説明がないので、自分でサンプルを書いてみる。複数のキーのJoinは元の本家のでドキュメントに記述がある。
オーバーロードが2つあるが、この表がわかりやすい。IEqualityComparer<T>
のありなしの違いのようだ。
基本的な意味合いは
IEnumerable<TOuter> :
インナージョインを実施する時の対抗のコレクション
Func<TOuter,TKey> :
アウターのコレクションのうち、Joinを実施したいカラムを指定する。複数のキーの場合、Tuple を使うと便利
Func<TInner,TKey> :
インナーのコレクションのうち、Joinを実施したいカラムを指定する。複数のキーの場合、Tuple を使うと便利
Func<TOuter, TInner, TResult> :
Join するコレクションがわたってくるので、結果を生成するファンクションをて定義する。
これだけだ。あと試していないけど、IEqualityCompare<T>
を使うと、自分のカスタムで、インターとアウターのキーが同値であることを定義できるのだろう。
あと、知らなかったけど、こういうときに、record を使うと、サンプル書くのが楽になるんやなぁ。
Query Expression と Lambda Expression は本質的に同じで、書き方が違うだけなので、定義で理解したほうが楽ですね。
サンプル
void Main()
{
List<Employee> employees = new()
{
new(FirstName: "Terry", LastName: "Adams", EmployeeID: 522459),
new("Charlotte", "Weiss", 204467),
new("Magnus", "Hedland", 866200),
new("Vernette", "Price", 437139)
};
List<Student> students = new()
{
new(FirstName: "Vernette", LastName: "Price", StudentID: 9562),
new("Terry", "Earls", 9870),
new("Terry", "Adams", 9913)
};
// Query expression
var query =
from employee in employees
join student in students on new
{
employee.FirstName,
employee.LastName
} equals new
{
student.FirstName,
student.LastName
}
select employee.FirstName + " " + employee.LastName;
Console.WriteLine("The following people are both employees and students:");
foreach (string name in query) {
Console.WriteLine(name);
}
// Lambda expression
var lambda = employees.Join(students,
employee => new {employee.FirstName, employee.LastName},
student => new {student.FirstName, student.LastName},
(employee, student) => $"{employee.FirstName} {employee.LastName}");
foreach (string name in lambda) {
Console.WriteLine(name);
}
}
public record Student(string FirstName, string LastName, int StudentID);
public record Employee(string FirstName, string LastName, int EmployeeID);
The following people are both employees and students:
Terry Adams
Vernette Price
Terry Adams
Vernette Price