블로그 이미지
따시쿵

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2015. 6. 18. 10:44 C# with LINQ to SQL

이번 포스트에서는 Group by 로 데이타 분류하기를 다뤄보도록 하겠습니다.

 

기본 문법

 

group A by B into C

 

A 에는 from 절에서 뽑아낸 범위 범수  

B 에는 분류 기준

C 에는 그룹 변수를 위치 시킵니다.

 

 

예제1

 

학생들의 점수를 나타내는 클래스를 대상으로 80점 미만인가? 80점 이상인가를 group by 절을 이용해서 작성해 보도록 하겠습니다.

    class Profile
    {
        public string Name { get; set; }
        public int Score { get; set; }
    }

    Profile[] arrProflie = {
                                new Profile(){Name="이순신",    Score=65},
                                new Profile(){Name="을지문덕",  Score=88},
                                new Profile(){Name="강감찬",    Score=79},
                                new Profile(){Name="세종대왕",  Score=59},
                                new Profile(){Name="장영실",    Score=90}
                            };

 

이 데이타를 group by 절을 이용해서 분류해 보겠습니다.

    var listProfile = from profile in arrProflie
                      orderby profile.Score
                      group profile by profile.Score < 80 into g
                      select new { GroupKey = g.Key, Profiles = g };

 

위의 쿼리식의 그룹 변수 g에는 Score 값이 80점 미만인 객체의 컬렉션, 80점 이상인 객체의 컬렉센이 입력되고, select 문이 추출하는 새로운 무명 향식은 컬렉션의 컬렉션이 됩니다. 그리고 이 무명형식의 Profiles 필드는 바로 이 그룹 변수 g를 담게 됩니다. 정렬은 점수 오름차순입니다. 최종적으로 쿼리의 결과를 다담은 listProfiles은 다음과 같은 모습을 할 것입니다.

 

 

전체 소스

    class Profile
    {
        public string Name { get; set; }
        public int Score { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Profile[] arrProflie = {
                                        new Profile(){Name="이순신",    Score=65},
                                        new Profile(){Name="을지문덕",  Score=88},
                                        new Profile(){Name="강감찬",    Score=79},
                                        new Profile(){Name="세종대왕",  Score=59},
                                        new Profile(){Name="장영실",    Score=90}
                                    };

            var listProfile = from profile in arrProflie
                              orderby profile.Score
                              group profile by profile.Score < 80 into g
                              select new { GroupKey = g.Key, Profiles = g };

            foreach(var Group in listProfile)
            {
                Console.WriteLine(" - 80점 미만? : {0}", Group.GroupKey);

                foreach(var profile in Group.Profiles)
                {
                    Console.WriteLine("{0}, {1}", profile.Name, profile.Score);
                }

                Console.WriteLine();
            }

            Console.ReadLine();
        }
    }

 

 

 

예제2 -  단일 속성을 그룹키로 사용하여 그룹화 시키기

 

학년별 학생들의 점수를 표시하기 위해 StudentClass 를 정의 합니다. 그리고 데이타도 같이 추가해 줍니다.

    public class StudentClass
    {
        #region data
        protected enum GradeLevel { FirstYear = 1, SecondYear, ThirdYear, FourthYear };
        protected class Student
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public int ID { get; set; }
            public GradeLevel Year;
            public List<int> ExamScores;
        }

        protected static List<Student> = new List<Student>
        {
            new Student {FirstName = "Terry", LastName = "Adams", ID = 120, Year = GradeLevel.SecondYear, ExamScores = new List<int>{ 99, 82, 81, 79}},
            new Student {FirstName = "Fadi", LastName = "Fakhouri", ID = 116, Year = GradeLevel.ThirdYear,ExamScores = new List<int>{ 99, 86, 90, 94}},
            new Student {FirstName = "Hanying", LastName = "Feng", ID = 117, Year = GradeLevel.FirstYear, ExamScores = new List<int>{ 93, 92, 80, 87}},
            new Student {FirstName = "Cesar", LastName = "Garcia", ID = 114, Year = GradeLevel.FourthYear,ExamScores = new List<int>{ 97, 89, 85, 82}},
            new Student {FirstName = "Debra", LastName = "Garcia", ID = 115, Year = GradeLevel.ThirdYear, ExamScores = new List<int>{ 35, 72, 91, 70}},
            new Student {FirstName = "Hugo", LastName = "Garcia", ID = 118, Year = GradeLevel.SecondYear, ExamScores = new List<int>{ 92, 90, 83, 78}},
            new Student {FirstName = "Sven", LastName = "Mortensen", ID = 113, Year = GradeLevel.FirstYear, ExamScores = new List<int>{ 88, 94, 65, 91}},
            new Student {FirstName = "Claire", LastName = "O'Donnell", ID = 112, Year = GradeLevel.FourthYear, ExamScores = new List<int>{ 75, 84, 91, 39}},
            new Student {FirstName = "Svetlana", LastName = "Omelchenko", ID = 111, Year = GradeLevel.SecondYear, ExamScores = new List<int>{ 97, 92, 81, 60}},
            new Student {FirstName = "Lance", LastName = "Tucker", ID = 119, Year = GradeLevel.ThirdYear, ExamScores = new List<int>{ 68, 79, 88, 92}},
            new Student {FirstName = "Michael", LastName = "Tucker", ID = 122, Year = GradeLevel.FirstYear, ExamScores = new List<int>{ 94, 92, 91, 91}},
            new Student {FirstName = "Eugene", LastName = "Zabokritski", ID = 121, Year = GradeLevel.FourthYear, ExamScores = new List<int>{ 96, 85, 91, 60}}
        };
        #endregion
    }

 

예제에서는 학생들의 LastName 을 키로 사용합니다. 또한 부분 문자열을 키로 사용할 수도 있습니다. 그룹화 작업은 형식에 대해 같은 연산자(equal, ==)를 사용합니다.

 

아래는 실제로 그룹화 작업을 수행하는 method 입니다. Group의 변수는 IGroup<T> 형식입니다.

        public void GroupBySingleProperty()
        {
            Console.WriteLine("Group by a single property in an object:\n");

            // Variable queryLastNames is an IEnumerable<IGROUPING<string, DataClass.Student>>.  
            var queryLastNames =
                from student in students
                group student by student.LastName into newGroup
                orderby newGroup.Key
                select newGroup;

            foreach (var nameGroup in queryLastNames)
            {
                Console.WriteLine("Key: {0}", nameGroup.Key);
                foreach (var student in nameGroup)
                {
                    Console.WriteLine("\t{0}, {1}", student.LastName, student.FirstName);
                }
            }
        }

 

전체 소스

    public class StudentClass
    {
        #region data
        protected enum GradeLevel { FirstYear = 1, SecondYear, ThirdYear, FourthYear };
        protected class Student
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public int ID { get; set; }
            public GradeLevel Year;
            public List<int> ExamScores;
        }

        protected static List<Student> students = new List<Student>
        {
            new Student {FirstName = "Terry", LastName = "Adams", ID = 120, Year = GradeLevel.SecondYear, ExamScores = new List<int>{ 99, 82, 81, 79}},
            new Student {FirstName = "Fadi", LastName = "Fakhouri", ID = 116, Year = GradeLevel.ThirdYear,ExamScores = new List<int>{ 99, 86, 90, 94}},
            new Student {FirstName = "Hanying", LastName = "Feng", ID = 117, Year = GradeLevel.FirstYear, ExamScores = new List<int>{ 93, 92, 80, 87}},
            new Student {FirstName = "Cesar", LastName = "Garcia", ID = 114, Year = GradeLevel.FourthYear,ExamScores = new List<int>{ 97, 89, 85, 82}},
            new Student {FirstName = "Debra", LastName = "Garcia", ID = 115, Year = GradeLevel.ThirdYear, ExamScores = new List<int>{ 35, 72, 91, 70}},
            new Student {FirstName = "Hugo", LastName = "Garcia", ID = 118, Year = GradeLevel.SecondYear, ExamScores = new List<int>{ 92, 90, 83, 78}},
            new Student {FirstName = "Sven", LastName = "Mortensen", ID = 113, Year = GradeLevel.FirstYear, ExamScores = new List<int>{ 88, 94, 65, 91}},
            new Student {FirstName = "Claire", LastName = "O'Donnell", ID = 112, Year = GradeLevel.FourthYear, ExamScores = new List<int>{ 75, 84, 91, 39}},
            new Student {FirstName = "Svetlana", LastName = "Omelchenko", ID = 111, Year = GradeLevel.SecondYear, ExamScores = new List<int>{ 97, 92, 81, 60}},
            new Student {FirstName = "Lance", LastName = "Tucker", ID = 119, Year = GradeLevel.ThirdYear, ExamScores = new List<int>{ 68, 79, 88, 92}},
            new Student {FirstName = "Michael", LastName = "Tucker", ID = 122, Year = GradeLevel.FirstYear, ExamScores = new List<int>{ 94, 92, 91, 91}},
            new Student {FirstName = "Eugene", LastName = "Zabokritski", ID = 121, Year = GradeLevel.FourthYear, ExamScores = new List<int>{ 96, 85, 91, 60}}
        };
        #endregion

        //Helper method, used in GroupByRange. 
        protected static int GetPercentile(Student s)
        {
            double avg = s.ExamScores.Average();
            return avg > 0 ? (int)avg / 10 : 0;
        }        

        public void QueryHighScores(int exam, int score)
        {
            var highScores = from student in students
                             where student.ExamScores[exam] > score
                             select new { Name = student.FirstName, Score = student.ExamScores[exam] };

            foreach (var item in highScores)
            {
                Console.WriteLine("{0,-15}{1}", item.Name, item.Score);
            }
        }

        public void GroupBySingleProperty()
        {
            Console.WriteLine("single property[LastName] 로 그룹화 시키기:\n");

            // Variable queryLastNames is an IEnumerable<IGrouping<string,  
            // DataClass.Student>>.  
            var queryLastNames =
                from student in students
                group student by student.LastName into newGroup
                orderby newGroup.Key
                select newGroup;

            foreach (var nameGroup in queryLastNames)
            {
                Console.WriteLine("Key: {0}", nameGroup.Key);
                foreach (var student in nameGroup)
                {
                    Console.WriteLine("\t{0}, {1}", student.LastName, student.FirstName);
                }
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            StudentClass sc = new StudentClass();
            sc.GroupBySingleProperty();

            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }

 

 

 

예제3 - 개체의 속성(property)이 아닌 항목을 그룹 키로 사용하는 경우

 

위에서 사용한 StudentClass 를 계속 사용합니다.

 

이 예제에서 키는 학생의 LastName 중에서 첫 번째 문자입니다. 첫번째 문자를 가지고 그룹화를 시키는 method 는 아래와 같습니다.

        public void GroupBySubstring()
        {
            Console.WriteLine("\r\nLastName 의 첫글자를 가지고 그룹화 사키기:");

            var queryFirstLetters =
                from student in students
                group student by student.LastName[0] into newGroup
                orderby newGroup.Key
                select newGroup;

            foreach (var studentGroup in queryFirstLetters)
            {
                Console.WriteLine("Key: {0}", studentGroup.Key);
                // Nested foreach is required to access group items. 
                foreach (var student in studentGroup)
                {
                    Console.WriteLine("\t{0}, {1}", student.LastName, student.FirstName);
                }
            }
        }

 

 

posted by 따시쿵