2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

LINQ で複数項目を対象にしたインナージョインを実現する

Last updated at Posted at 2022-06-27

二つの集合の重複する部分を検出して、重複個所のファイルを削除するクエリをさっと書きたいと思った。
LINQ でできるだろうと思っていたのだけど、やり方を知らなかったので調べた。

Join

普通にJoinがあるようだ。
image.png

ここに書いているが、Query expression だった。普段私は Lambda expression を使うので両方で使ってみよう。変換はこちらのブログ
が参考になりそうだが、残念ながら、複数のキーでのJoinに関しては説明がないので、自分でサンプルを書いてみる。複数のキーのJoinは元の本家のでドキュメントに記述がある。

定義は Enumerable.Join Method
image.png

オーバーロードが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
2
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?