C#/LINQ

[C#]LINQ SelectMany 메서드

DevStory 2022. 7. 10.

SelectMany 메서드

LINQ의 SelectMany() 메서드는 질의 구문에서 사용할 수 없으며 메서드 구문에서 사용할 수 있는 기능입니다.

 

.NET 공식 문서에서는 SelectMany() 메서드를 다음과 같이 정의합니다.

시퀀스의 각 요소를 IEnumerable<T>에 투영하고 결과 시퀀스를 단일 시퀀스로 평면화합니다.

음... 솔직하게 무슨 말인지 이해가 안 되네요.

 

예제를 통해 SelectMany() 메서드가 어떻게 동작하는지 알아봅시다. 다음 예제는 string 타입으로 구성된 List에서 SelectMany() 메서드를 호출합니다.

class Program
{
  static void Main(string[] args)
  {
    List<string> strLi = new List<string>()
    {
      "Hello", "C Sharp"
    };

    List<char> selectManyResult = strLi.SelectMany(item => item).ToList();

    foreach (char obj in selectManyResult)
      Console.WriteLine(obj);
  }
}

[실행 결과]

H
e
l
l
o
C

S
h
a
r
p

위 예제에서 주목해야 하는 점은 SelectMany() 메서드 결과를 ToList() 메서드를 사용하여 List로 변환했는데, List<char>으로 반환했다는 점입니다.

 

즉, SelectMany() 메서드는 추출하는 항목을 세부적인 요소로 반환한다는 것입니다. string은 char 타입의 집합이므로 char 타입으로 반환되었습니다.


질의 구문에서 사용

SelectMany() 메서드는 질의 구문에서 지원되지 않습니다. 그러나 다음 예제와 같이 from문을 한 번 더 사용하면 SelectMany() 메서드를 사용하는 것처럼 동작합니다.

class Program
{
  static void Main(string[] args)
  {
    List<string> strLi = new List<string>()
    {
      "Hello", "C Sharp"
    };

    List<char> selectManyResult = (from   str in strLi
                                   from   ch  in str
                                   select ch).ToList();

    foreach (char obj in selectManyResult)
      Console.WriteLine(obj);
  }
}

[실행 결과]

H
e
l
l
o
C

S
h
a
r
p

예제 1. 사용자 정의 클래스

그렇다면, 다음 소스 코드처럼 사용자 정의 클래스로 구성된 List에서 SelectMany() 메서드를 사용한다면 어떻게 동작할까요?

class Person
{
  public int ID { get; set; }
  public string Name { get; set; }
  public List<string> Subject { get; set; }
}

class Program
{
  static void Main(string[] args)
  {
    List<Person> person = new List<Person>
    {
      new Person() { ID = 100, Name = "Bob",     Subject = new List<string> { "C#", "Java"} },
      new Person() { ID = 200, Name = "Tim",     Subject = new List<string> { "C++", "JS"} },
      new Person() { ID = 300, Name = "Charles", Subject = new List<string> { "React"} }
    };
  }
}

위에서 설명했듯이 SelectMany() 메서드는 추출하고자 하는 항목을 세부적인 요소로 반환한다고 설명하였습니다. Person 클래스에는 List<string>타입인 Subject 프로퍼티가 존재합니다.

 

List<string>은 string의 집합이므로 SelectMany() 메서드를 사용하여 List의 각 요소를 추출할 수 있습니다.

class Person
{
  public int ID { get; set; }
  public string Name { get; set; }
  public List<string> Subject { get; set; }
}

class Program
{
  static void Main(string[] args)
  {
    List<Person> person = new List<Person>
    {
      new Person() { ID = 100, Name = "Bob",     Subject = new List<string> { "C#", "Java"} },
      new Person() { ID = 200, Name = "Tim",     Subject = new List<string> { "C++", "JS"} },
      new Person() { ID = 300, Name = "Charles", Subject = new List<string> { "React"} }
    };

    // 1. 질의 구문(Query Syntax)
    List<string> linqQueryResult = (from   obj     in person
                                    from   subject in obj.Subject
                                    select subject).ToList();

    // 2. 메서드 구문(Method Syntax)
    List<string> linqMethodResult = person.SelectMany(item => item.Subject).ToList();

    Console.WriteLine("질의 구문");
    foreach (string str in linqQueryResult)
      Console.WriteLine(str);

    Console.WriteLine("\n메서드 구문");
    foreach (string str in linqMethodResult)
      Console.WriteLine(str);
  }
}

[실행 결과]

질의 구문
C#
Java
C++
JS
React

메서드 구문
C#
Java
C++
JS
React

예제 2. 여러 프로퍼티 추출

여러 프로퍼티를 추출하고 싶은 경우 익명 타입인 var 키워드를 사용합니다.

class Person
{
  public int ID { get; set; }
  public string Name { get; set; }
  public List<string> Subject { get; set; }
}

class Program
{
  static void Main(string[] args)
  {
    List<Person> person = new List<Person>
    {
      new Person() { ID = 100, Name = "Bob",     Subject = new List<string> { "C#", "Java"} },
      new Person() { ID = 200, Name = "Tim",     Subject = new List<string> { "C++", "JS"} },
      new Person() { ID = 300, Name = "Charles", Subject = new List<string> { "React"} }
    };

    // 1. 질의 구문(Query Syntax)
    var linqQueryResult = (from   obj     in person
                           from   subject in obj.Subject
                           select new
                           {
                             Name = obj.Name,
                             Subject = subject
                           }).ToList();

    // 2. 메서드 구문(Method Syntax)
    var linqMethodResult = person
        .SelectMany(item => item.Subject,
          (student, subject) => new
          {
            Name = student.Name,
            Subject = subject
          }).ToList();


    Console.WriteLine("질의 구문");
    foreach (var obj in linqQueryResult)
      Console.WriteLine("Name: " + obj.Name + " / Subject: " + obj.Subject);

    Console.WriteLine("\n메서드 구문");
    foreach (var obj in linqMethodResult)
      Console.WriteLine("Name: " + obj.Name + " / Subject: " + obj.Subject);
  }
}

[실행 결과]

질의 구문
Name: Bob / Subject: C#
Name: Bob / Subject: Java
Name: Tim / Subject: C++
Name: Tim / Subject: JS
Name: Charles / Subject: React

메서드 구문
Name: Bob / Subject: C#
Name: Bob / Subject: Java
Name: Tim / Subject: C++
Name: Tim / Subject: JS
Name: Charles / Subject: React
반응형

'C# > LINQ' 카테고리의 다른 글

[C#]LINQ 인덱스 가져오는 방법  (0) 2022.07.12
[C#]LINQ 데이터 필터링 방법 - Where절  (0) 2022.07.10
[C#]LINQ Select절  (0) 2022.07.10
[C#]LINQ 확장 메서드  (0) 2022.07.10
[C#]LINQ와 IEnumerable, IQueryable 인터페이스  (0) 2022.07.10

댓글