이번 포스트에서는 Group by 로 데이타 분류하기를 다뤄보도록 하겠습니다.
group A by B into C
A 에는 from 절에서 뽑아낸 범위 범수
B 에는 분류 기준
C 에는 그룹 변수를 위치 시킵니다.
학생들의 점수를 나타내는 클래스를 대상으로 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(); } }
학년별 학생들의 점수를 표시하기 위해 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(); } }
위에서 사용한 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); } } }
'C# with LINQ to SQL' 카테고리의 다른 글
LINQ - 4칙 연산(select, insert, update, delete) - DataGridView 이용 (0) | 2015.07.01 |
---|---|
LINQ - 로그인창 적용 (0) | 2015.06.25 |
LINQ - 조인(내부조인, 그룹조인, 왼쪽 우선 외부 조인) (0) | 2015.06.22 |
LINQ - 그룹핑2 (0) | 2015.06.19 |
LINQ - 소개 (0) | 2015.06.16 |