집게사장의 꿈

LINQ 메서드 GroupBy 본문

기타/C#

LINQ 메서드 GroupBy

Krapboss 2024. 7. 23. 22:31

지정한 키값을 기준으로 지정된 요소를 분류하는 함수

GroupBy


 

 

 

1. 키 선택기를 이용해 시퀀스 요소를 그룹화 하고 그룹 내 요소는 지정된 함수를 통해 형식을 지정한다.

public static System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult> (this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector, Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);

반환
IEnumerable<TResult>
각 요소가 그룹과 해당 키에 대한 프로젝션을 나타내는 TResult 형식의 요소 컬렉션입니다.

예외
ArgumentNullExceptionsource, keySelector, elementSelector 또는 resultSelector가 null인 경우

 

Func<TSource,TKey> keySelector,  그룹의 키를 선택하는 대리자
Func<TSource,TElement> elementSelector, 분류된 그룹의 엘리먼트를 지정하는 대리자
Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector); 키값에 해당하는 시퀀스를 받아 그룹의 최종 결과값을 반환하는 대리자

 

class Pet
{
    public string Name { get; set; }
    public double Age { get; set; }
}
internal class GroupBy // 웰컴 키트 
{
    static void Main(string[] args)
    {
        List<Pet> petsList =
        new List<Pet>{ new Pet { Name="Barley", Age=8.3 },
                   new Pet { Name="Boots", Age=4.9 },
                   new Pet { Name="Whiskers", Age=1.5 },
                   new Pet { Name="Daisy", Age=4.3 } };

        var query = petsList.GroupBy(
            pet => Math.Floor(pet.Age), //age를 기준으로 그룹을 분류한다.
            pet => pet.Age,             //age로 분류된 값에 엘리먼스 값으로 지정할 변수
            (baseAge, ages) => new      // ages는 그룹으로 분류된 시퀀스
            {
                Key = baseAge,          //그룹으로 분류된 키값
                Count = ages.Count(),   //분류된 개수
                Min = ages.Min(),       //엘리먼트 중 최소값
                Max = ages.Max()        //엘리먼트 중 최대값
            }) ;

        // Iterate over each anonymous type.
        foreach (var result in query)
        {
            Console.WriteLine("\nAge group: " + result.Key);
            Console.WriteLine("Number of pets in this age group: " + result.Count);
            Console.WriteLine("Minimum age: " + result.Min);
            Console.WriteLine("Maximum age: " + result.Max);
        }
    }
}

 

 

 

 


2. 키 선택기를 이용해 시퀀스 요소를 그룹화 하고 그룹 내 요소들을 지정한다.

public static System.Collections.Generic.IEnumerable<System.Linq.IGrouping<TKey,TElement>> GroupBy<TSource,TKey,TElement> (
this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector);

 

Func<TSource,TKey> keySelector, 그룹 분류를 위한 키값을 지정합니다.
Func<TSource,TElement> elementSelector 키 값에 따른 그룹 내 요소들을 지정합니다.

 

class Pet
{
    public string Name { get; set; }
    public int Age { get; set; }
}
internal class GroupBy // 웰컴 키트 
{
    static void Main(string[] args)
    {
        // Create a list of pets.
        List<Pet> pets =
            new List<Pet>{ new Pet { Name="Barley", Age=8 },
                   new Pet { Name="Boots", Age=4 },
                   new Pet { Name="Whiskers", Age=1 },
                   new Pet { Name="Daisy", Age=4 } };

        IEnumerable<IGrouping<int, string>> query =
            pets.GroupBy(
                pet => pet.Age,     //키값을 지정합니다. 키값을 통해 그룹을 분류합니다.
                pet => pet.Name);   // 키값에 따른 그룹내 요소입니다.

        // Iterate over each IGrouping in the collection.
        foreach (IGrouping<int, string> petGroup in query)
        {
            Console.WriteLine(petGroup.Key);

            foreach (string name in petGroup)
            {
                Console.WriteLine("  {0}", name);
            }
        }
    }
}

 

 

여기서 분류된 그룹 값은 각 그룹의 Element에 대한 IEnumerable을 상속받았기에 반복기를 돌릴 수 있다.


 

3. 지정된 키 누적기 함수에 따라 시퀀스의 요소를 그룹화하고 각 그룹의 결과 값과 해당 키를 만든다.

public static System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TResult> (this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TKey,System.Collections.Generic.IEnumerable<TSource>,TResult> resultSelector);

 

Func<TSource,TKey> keySelector 키값을 지정합니다.
Func<TKey,System.Collections.Generic.IEnumerable<TSource>,TResult> resultSelector 키값으로 분류된 TSource 값을 받아 사용자가 정의한 형식값을 TResult로 반환합니다.

 

class Pet
{
    public string Name { get; set; }
    public double Age { get; set; }
}
internal class GroupBy // 웰컴 키트 
{
    static void Main(string[] args)
    {
        // Create a list of pets.
        List<Pet> petsList =
            new List<Pet>{ new Pet { Name="Barley", Age=8.3 },
                   new Pet { Name="Boots", Age=4.9 },
                   new Pet { Name="Whiskers", Age=1.5 },
                   new Pet { Name="Daisy", Age=4.3 } };

        var query = petsList.GroupBy(
            pet => Math.Floor(pet.Age),         //키값
            (age, pets) => new                  //각 그룹의 결과값을 나타낸다.
            {
                Key = age,                      // 키값을 지정
                Count = pets.Count(),           //각 그룹의 펫 수를 지정
                Min = pets.Min(pet => pet.Age), //각 그룹의 최소 나잇값을 지정
                Max = pets.Max(pet => pet.Age)  //각 그룹의 최대 나잇값을 지정
            }); ;

        // Iterate over each anonymous type.
        foreach (var result in query)
        {
            Console.WriteLine("\nAge group: " + result.Key);
            Console.WriteLine("Number of pets in this age group: " + result.Count);
            Console.WriteLine("Minimum age: " + result.Min);
            Console.WriteLine("Maximum age: " + result.Max);
        }
    }
}

 

 

 


4. 키 값만 지정하고, 지정된 키 값에 따라 엘리먼트들이 분류되는 경우

public static System.Collections.Generic.IEnumerable<System.Linq.IGrouping<TKey,TSource>> GroupBy<TSource,TKey> (
this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector);

 

*실제 백준에서 사용하는 경우(0~9 까지의 숫자가 각각 등장한 횟수)

internal class E2577_ADD // 숫자의 개수
{
    static void Main(string[] args)
    {
        int multiple = 1456841569;
        //for (int i = 0; i < 3; i++) multiple *= int.Parse(Console.ReadLine());

        //각 숫자의 개수를 세아리는 구문
        //숫자 문자열 별로 그룹화하고, 각 엘리먼트를 값으로 지정한다.
        //각 키 값에는 엘리먼트들이 존재한다.
        var count = multiple.ToString().GroupBy(x => x).ToDictionary(x => x.Key, (x) => x.Count());

        //각 0~9까지의 수를 오름차순으로 정렬하는 구문
        var allDigits = Enumerable.Range(0, 10).Select(d => d.ToString()[0]);
        var result = allDigits
            .Select(d => new { Digit = d, Count = count.ContainsKey(d) ? count[d] : 0 })
            .OrderBy(x => x.Digit);

        foreach (var item in result) { Console.WriteLine($"{item.Digit} : {item.Count}"); }       
    }
}

 

 

 

 


 

[출처]

https://learn.microsoft.com/ko-kr/dotnet/api/system.linq.enumerable.groupby?view=net-8.0#system-linq-enumerable-groupby-2(system-collections-generic-ienumerable((-0))-system-func((-0-1)))

 

Enumerable.GroupBy 메서드 (System.Linq)

시퀀스의 요소를 그룹화합니다.

learn.microsoft.com

 

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

LINQ 집합  (0) 2024.07.23
LINQ 집계함수  (0) 2024.07.23
LINQ 메서드  (0) 2024.07.23
C# LINQ 쿼리 키워드  (0) 2024.07.21
C# LINQ 소개  (0) 2024.07.21