리스트를 평탄화(flatten)한다는 것은 List<List<T>>처럼 중첩된 리스트 구조를 단일 List<T>로 변환하는 작업을 의미합니다. 예를 들어 여러 개의 정수 리스트를 담고 있는 List<List<int>>를 하나의 List<int>로 합쳐야 하는 경우가 대표적입니다.
LINQ의 SelectMany 연산자는 시퀀스의 각 요소를 IEnumerable<T>로 프로젝션한 뒤, 그 결과로 만들어진 여러 시퀀스를 하나의 시퀀스로 병합하는 역할을 합니다. 즉, 여러 개의 결과 집합에 나뉘어 있는 데이터를 하나의 결과로 합쳐 줍니다.
1. SelectMany 메서드 구문 사용하기
예제
using System;
using System.Collections.Generic;
using System.Linq;
namespace DemoApplication{
public class Program{
static void Main(string[] args){
List<List<int>> listOfNumLists = new List<List<int>>{
new List<int>{
1, 2
},
new List<int>{
3, 4
}
};
var numList = listOfNumLists.SelectMany(i => i);
Console.WriteLine("리스트의 숫자:");
foreach(var num in numList){
Console.WriteLine(num);
}
Console.ReadLine();
}
}
}실행 결과
리스트의 숫자: 1 2 3 4
SelectMany(i => i)는 각 내부 리스트를 그대로 반환하도록 지정하므로, 중첩된 모든 요소가 하나의 시퀀스로 이어져 순서대로 출력됩니다.
2. 쿼리 구문(Query Syntax) 사용하기
예제
using System;
using System.Collections.Generic;
using System.Linq;
namespace DemoApplication{
public class Program{
static void Main(string[] args){
List<List<int>> listOfNumLists = new List<List<int>>{
new List<int>{
1, 2
},
new List<int>{
3, 4
}
};
var numList = from listOfNumList in listOfNumLists
from value in listOfNumList
select value;
Console.WriteLine("리스트의 숫자:");
foreach(var num in numList){
Console.WriteLine(num);
}
Console.ReadLine();
}
}
}실행 결과
리스트의 숫자: 1 2 3 4
두 개의 from 절을 연달아 사용하면 외부 시퀀스의 각 요소에서 내부 시퀀스를 다시 순회하며 값을 하나씩 꺼낼 수 있습니다. 이 쿼리 구문은 컴파일 시점에 내부적으로 SelectMany 호출로 변환됩니다.
정리
메서드 구문(SelectMany)과 쿼리 구문은 컴파일 결과가 동일하므로 성능 차이는 없습니다. 코드 가독성과 팀의 코딩 스타일에 맞는 방식을 선택해 사용하면 됩니다.