3가지 LINQ 설정 메서드: Intersect, Union 및 Except

몇 주 전에 원래 이 게시물을 my blog에 게시했습니다. LINQ에 대한 포스트 시리즈의 일부입니다.

지금까지 most common LINQ methods의 일부를 다루었습니다. 이번에는 집합 작업처럼 작동하는 세 가지 LINQ 메서드인 Intersect, Union 및 Except를 살펴보겠습니다. 아마도 우리는 이러한 방법을 매일 사용하지 않을 것이지만 때때로 유용할 것입니다.

이 시리즈의 이전 게시물에 있는 영화 카탈로그를 사용하여 이 세 가지 방법이 어떻게 작동하는지 보여드리겠습니다.

1. 교차



Intersect() 메서드는 두 컬렉션 간의 공통 요소를 찾습니다.

카탈로그에서 우리 둘 다 보고 평가한 영화를 찾아봅시다.

var mine = new List<Movie>
{
    // We have not exactly a tie here...
    new Movie("Terminator 2", 1991, 4.7f),
    //        ^^^^^^^^^^^^^^
    new Movie("Titanic", 1998, 4.5f),
    new Movie("The Fifth Element", 1997, 4.6f),
    new Movie("My Neighbor Totoro", 1988, 5)
    //        ^^^^^^^^^^^^^^^^^^^^
};

var yours = new List<Movie>
{
    new Movie("My Neighbor Totoro", 1988, 5f),
    //        ^^^^^^^^^^^^^^^^^^^^
    new Movie("Pulp Fiction", 1994, 4.3f),
    new Movie("Forrest Gump", 1994, 4.3f),
    // We have not exactly a tie here...
    new Movie("Terminator 2", 1991, 5f)
    //        ^^^^^^^^^^^^^^
};

var weBothHaveSeen = mine.Intersect(yours);
Console.WriteLine("We both have seen:");
PrintMovies(weBothHaveSeen);

// Output:
// We both have seen:
// My Neighbor Totoro

Console.ReadKey();

static void PrintMovies(IEnumerable<Movie> movies)
{
      Console.WriteLine(string.Join(",", movies.Select(movie => movie.Name)));
}

record Movie(string Name, int ReleaseYear, float Rating);


이번에는 mineyours 두 개의 영화 목록이 있으며 각각 내가 본 영화와 귀하가 본 것으로 추측되는 영화가 있습니다. 또한 우리 둘 다 "이웃집 토토로"와 "터미네이터 2"를 본 것을 주목하세요.

우리 둘 다 본 영화(두 카탈로그 사이의 교차점)를 찾기 위해 Intersect() 방법을 사용했습니다. 하지만 이 예에서는 "이웃집 토토로"만 보여줍니다. 여기 뭔 일 있었 니?

자세히 보면 둘 다 '터미네이터2'를 봤는데 평가가 달랐다. records from C# 9.0 을 사용하고 있으므로 레코드는 멤버별로 비교됩니다. 따라서 두 개의 "터미네이터 2"인스턴스는 이름과 출시 연도가 같더라도 완전히 동일하지 않습니다. 이것이 Intersect()가 반환하지 않는 이유입니다.


해당 상자의 교차점과 합집합을 찾는 행운을 빕니다...CHUTTERSNAPUnsplash 사진 제공

2. 조합



Union() 메서드는 중복 없이 두 컬렉션의 요소를 찾습니다.

카탈로그에 있는 모든 영화를 찾아봅시다.

var mine = new List<Movie>
{
    new Movie("Terminator 2", 1991, 5f),
    //        ^^^^^^^^^^^^^^
    new Movie("Titanic", 1998, 4.5f),
    new Movie("The Fifth Element", 1997, 4.6f),
    new Movie("My Neighbor Totoro", 1988, 5f)
    //        ^^^^^^^^^^^^^^^^^^^^
};

var yours = new List<Movie>
{
    new Movie("My Neighbor Totoro", 1988, 5f),
    //        ^^^^^^^^^^^^^^^^^^^^
    new Movie("Pulp Fiction", 1994, 4.3f),
    new Movie("Forrest Gump", 1994, 4.3f),
    new Movie("Terminator 2", 1991, 5f)
    //        ^^^^^^^^^^^^^^
};

var allTheMoviesWeHaveSeen = mine.Union(yours);
Console.WriteLine("All the movies we have seen:");
PrintMovies(allTheMoviesWeHaveSeen);

// Output:
// All the movies we have seen:
// Terminator 2,Titanic,The Fifth Element,My Neighbor Totoro,Pulp Fiction,Forrest Gump

Console.ReadKey();

static void PrintMovies(IEnumerable<Movie> movies)
{
      Console.WriteLine(string.Join(",", movies.Select(movie => movie.Name)));
}

record Movie(string Name, int ReleaseYear, float Rating);


이번에는 공유 영화인 "터미네이터 2"와 "이웃집 토토로"에 동일한 등급을 부여했습니다. 그리고 Union()는 두 컬렉션의 모든 영화를 보여 주었고 복제본은 한 번만 표시했습니다. Math 클래스의 합집합 연산과 동일한 방식으로 작동합니다.

3. 제외



Except() 메서드는 한 컬렉션에서 다른 컬렉션에 없는 요소를 찾습니다.

이번에는 나만 본 영화를 찾아보자.

var mine = new List<Movie>
{
    new Movie("Terminator 2", 1991, 5f),
    new Movie("Titanic", 1998, 4.5f),
    //         ^^^^^^^
    new Movie("The Fifth Element", 1997, 4.6f),
    //         ^^^^^^^^^^^^^^^^^
    new Movie("My Neighbor Totoro", 1988, 5f)
};

var yours = new List<Movie>
{
    new Movie("My Neighbor Totoro", 1988, 5f),
    new Movie("Pulp Fiction", 1994, 4.3f),
    new Movie("Forrest Gump", 1994, 4.3f),
    new Movie("Terminator 2", 1991, 5f)
};

var onlyIHaveSeen = mine.Except(yours);
Console.WriteLine();
Console.WriteLine("Only I have seen:");
PrintMovies(onlyIHaveSeen);

// Output:
// Only I have seen:
// Titanic,The Fifth Element

Console.ReadKey();

static void PrintMovies(IEnumerable<Movie> movies)
{
      Console.WriteLine(string.Join(",", movies.Select(movie => movie.Name)));
}

record Movie(string Name, int ReleaseYear, float Rating);

Except() 를 사용하여 mine 에 없고 yours 에 없는 영화를 찾았습니다. Except() 로 작업할 때 mine.Except(yours)yours.Except(mine) 와 같지 않기 때문에 컬렉션 순서에 주의해야 합니다.

짜잔! Intersect() , Union()Except() 메서드입니다. 그것들은 각각 교집합, 합집합, 대칭 차이 등의 수학 집합 연산처럼 작동합니다. 세 가지 중에서 Except가 가장 일반적인 방법입니다.

LINQ에는 두 개의 컬렉션을 하나의 컬렉션으로 "결합"하는 유사한 방법이 있습니다. Concat() . 그러나 Union() 와 달리 Concat() 는 중복 컬렉션을 제거하지 않고 두 컬렉션의 모든 요소를 ​​반환합니다.

.NET 6에는 keySelector와 함께 작동하는 IntersectBy() , UnionBy()ExceptBy() 메서드가 있어 교차, 결합 또는 제외할 속성으로 사용할 속성을 선택합니다. IntersectBy() 를 사용하면 첫 번째 예에서 mineyours 에 정확히 동일한 레코드가 없어도 "터미네이터 2"를 다시 가져올 수 있습니다.

LINQ 및 기타 방법에 대해 알아보려면 내 블로그에서 my quick guide to LINQwhat's new in LINQ with .NET6을 확인하십시오.

여기요! 저는 소프트웨어 엔지니어이자 평생 학습자인 Cesar입니다. 내 작업을 지원하려면 다른 LINQ 메서드를 자세히 다루는 Educative에서 내Getting Started with LINQ course를 확인하세요.

즐거운 코딩하세요!

좋은 웹페이지 즐겨찾기