(C# Linq) Select와 SelectMany의 차이점

샘플 LINQ 코드를 보면 (ic)Select(/ic)와 (ic)SelectMany(/ic)가 일반적으로 사용됩니다.

알면 쉽지만 헷갈리기 시작하면 한없이 헷갈린다.

이 게시물을 통해 개념을 명확히 합시다.

샘플 목록 만들기

이것은 월드컵이 우승한 국가와 연도의 목록입니다.

List<Winner> list = new()
{
            new Winner() { Country = "Argentina", Years = new() { 1978, 1986, 2022 } },
            new Winner() { Country = "England  ", Years = new() { 1966 } },
            new Winner() { Country = "Germany  ", Years = new() { 1954, 1974, 1990, 2014 } },
};

적용 사례 선택

List<string> countries = list.Select(w => w.Country).ToList();
countries.ForEach(c => Console.WriteLine(c));

//output
Argentina
England
Germany

복잡한 객체 목록에서 원하는 부분을 간단히 추출하여 새로운 유형의 컬렉션을 만듭니다.

(기존 컬렉션에는 영향 없음)

하지만! 선택할 속성 값이 배열인 경우 (ic)Select(/ic)는 번거롭다.

List<int()> listOfArrays = list.Select(w => w.Years).ToList();
listOfArrays.ForEach(y => Console.WriteLine(y));

//output
System.Int32()
System.Int32()
System.Int32()

배열의 값이 보이지 않고 유형 이름만 표시되기 때문입니다.

해당 값을 읽으려면 이중 for 루프를 사용해야 합니다. 꽤 어색합니다.

이 경우 (ic)SelectMany(/ic)를 사용하면 편리하다.

SelectMany 사용 예

1) 파라미터가 1개일 경우

List<int> aggregatedList = list.SelectMany(w => w.Years).ToList();
aggregatedList.ForEach(y => Console.WriteLine(y));

//output
1978
1986
2022
1966
1954
1974
1990
2014

(ic) 이중 for 루프(/ic) 없이 목록의 값을 풀고 모음을 만듭니다.

그런데 그렇게만 풀면 어느 나라가 그 해를 이겼는지 알 수가 없습니다.

이 경우 두 개의 매개변수를 사용하면 문제를 해결할 수 있습니다.

2) 파라미터가 2개인 경우

var customList = list.SelectMany(w => w.Years, (w, y) => new { Country = w.Country, Year = y}).ToList();

복잡하고 특이한 모양입니다. 하나씩 분석해 봅시다.


신원

(ic)w(/ic)는 (ic)Winner(/ic) 객체가 전달되는 곳입니다.


y의 정체성

(ic)w => w.Years(/ic)에 의해 압축 해제된 (ic)Year 배열(/ic)은 (ic)y(/ic)로 전달됩니다.

새로 생성된 (ic)new { Country = w.Country, year =y } (/ic)는 어떻게 생겼습니까?


결과는 아래와 같습니다.

customList.ForEach(e => Console.WriteLine(e));

//output
{ Country = Argentina, Year = 1978 }
{ Country = Argentina, Year = 1986 }
{ Country = Argentina, Year = 2022 }
{ Country = England  , Year = 1966 }
{ Country = Germany  , Year = 1954 }
{ Country = Germany  , Year = 1974 }
{ Country = Germany  , Year = 1990 }
{ Country = Germany  , Year = 2014 }

결과는 작동 방식에 대한 느낌을 제공합니다.