더북(TheBook)

그룹 알고리즘 사용하기

그룹 알고리즘의 가장 기본적인 코드 형태를 살펴보겠습니다. 단 현재 그룹 알고리즘 예제는 아직 배우지 않은 클래스와 속성, 컬렉션 이니셜라이저 등의 개념이 들어 있습니다. 알고리즘을 주제로 12개를 묶어서 표현하다 보니 이곳에서 미리 소개했는데요. 일단은 코드 이해보다 ‘이렇게 하면 그룹이 되는구나’ 정도로 가볍게 실습 예제를 살펴보고 넘어갑니다. 나중에 기회가 되면 다시 한 번 이 부분을 찾아서 소스 코드를 확인하길 권장합니다.

컬렉션 형태의 데이터를 특정 키 값으로 그룹화: GroupAlgorithm.cs

using System;
using System.Collections.Generic;
using System.Linq;

class GroupAlgorithm
{
    class Record //테스트용 레코드 클래스
    {
        public string Name { get; set; }  //상품 이름
        public int Quantity { get; set; } //수량
    }

    static void Main()
    {
        //테스트용 데이터 채우기 로컬 함수
        List<Record> GetAll()
        {
            return new List<Record>
            {
                new Record { Name = "RADIO", Quantity = 3 },
                new Record { Name = "TV", Quantity = 1 },
                new Record { Name = "RADIO", Quantity = 2 },
                new Record { Name = "DVD", Quantity = 4 }
            };
        }

        //컬렉션 데이터 출력용 로컬 함수
        void PrintData(string message, List<Record> data)
        {
            Console.WriteLine(message);
            foreach (var item in data)
            {
                Console.WriteLine($"{item.Name,5} - {item.Quantity}");
            }
        }

        //① 입력
        List<Record> records = GetAll();          //입력 데이터
        List<Record> groups = new List<Record>(); //출력 데이터
        int N = records.Count;                    //의사코드

        //② 처리: Group 알고리즘(SORT -> SUM -> GROUP)
        //그룹 정렬: SORT
        for (int i = 0; i < N - 1; i++)
        {
            for (int j = i + 1; j < N; j++)
            {
                if (String.Compare(records[i].Name, records[j].Name) > 0)
                {
                    var t = records[i]; records[i] = records[j]; records[j] = t;
                }
            }
        }

        //그룹 소계: GROUP
        int subtotal = 0;                     //소계
        for (int i = 0; i < N; i++)
        {
            subtotal += records[i].Quantity;  //같은 상품 이름의 수량을 누적(SUM)
            if ((i + 1) == N ||              //단락이면 아래 조건 무시
                (records[i].Name != records[i + 1].Name))
            {
                //다음 레코드가 없거나 현재 레코드와 다음 레코드가 다르면 저장
                groups.Add(new Record
                {
                    Name = records[i].Name,    //한 그룹의 키(key) 지정
                    Quantity = subtotal        //소계
                });                            //한 그룹 저장

                subtotal = 0;                  //한 그룹이 완료되면 소계 초기화
            }
        }

        //③ 출력
        PrintData("[1] 정렬된 원본 데이터 : ", records);
        PrintData("[2] 이름으로 그룹화된 데이터 : ", groups);
        PrintData("[3] LINQ로 그룹화된 데이터 : ", records
            .GroupBy(r => r.Name).Select(g => new Record {
                Name = g.Key, Quantity = g.Sum(n => n.Quantity) }).ToList());
    }
}
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.