반응형
컬렉션 작업을 할때 가장 많이 이용하는 함수이기도 한 프로젝션과 요소작업 컬렉션 메소드에 대해 알아봅니다.
메서드
메서드 이름 | 설명 | C# 쿼리 식 구문 |
Select | 변환 함수를 기반으로 하는 값을 프로젝션합니다. | select |
SelectMany | 변환 함수를 기반으로 하는 값의 시퀀스를 프로젝션한 다음 하나의 시퀀스로 평면화합니다. | 여러 from 절 사용 |
Zip | 지정된 2~3개 시퀀스의 요소를 사용하여 튜플 시퀀스를 생성합니다. | |
ElementAt | 컬렉션의 지정된 인덱스에 있는 요소를 반환합니다. | |
ElementAtOrDefault | 컬렉션의 지정된 인덱스에 있는 요소를 반환하거나 인덱스가 범위를 벗어나면 기본값을 반환합니다. | |
First | 컬렉션의 첫 번째 요소 또는 특정 조건에 맞는 첫 번째 요소를 반환합니다. | |
FirstOrDefault | 컬렉션의 첫 번째 요소 또는 특정 조건에 맞는 첫 번째 요소를 반환합니다. 이러한 요소가 없으면 기본값을 반환합니다. | |
Last | 컬렉션의 마지막 요소 또는 특정 조건에 맞는 마지막 요소를 반환합니다. | |
LastOrDefault | 컬렉션의 마지막 요소 또는 특정 조건에 맞는 마지막 요소를 반환합니다. 이러한 요소가 없으면 기본값을 반환합니다. | |
Single | 컬렉션의 유일한 요소 또는 특정 조건에 맞는 유일한 요소를 반환합니다. 반환할 요소가 없거나 두 개 이상 있는 경우 InvalidOperationException을 throw합니다. | |
SingleOrDefault | 컬렉션의 유일한 요소 또는 특정 조건에 맞는 유일한 요소를 반환합니다. 반환할 요소가 없는 경우 기본값을 반환합니다. 반환할 요소가 두 개 이상 있는 경우 InvalidOperationException을 throw합니다. |
프로젝션
시퀀스에서 조건을 충족하는 요소가 일부인지 전체인지를 나타내는 Boolean 값을 반환
Select, SelectMany, Zip
List<Student> students = new List<Student>
{
new Student{grade = 3, name = "Tom", scores = new int[] {60, 80} },
new Student{grade = 3, name = "Brian" , scores = new int[] {50, 70} },
new Student{grade = 4, name = "Chris" , scores = new int[] {80, 80}},
new Student{grade = 5, name = "James" , scores = new int[] {100, 100} },
};
List<Teacher> teachers = new List<Teacher>
{
new Teacher{grade = 3, name = "Miss Christina" },
new Teacher{grade = 4, name = "Mr. Tayler" },
new Teacher{grade = 6, name = "Mr. Jone" },
new Teacher{grade = 5, name = "James" },
};
// 익명타입(새로운 형식)으로 표현
var select = students.Select(std => std);
foreach(var sel in select)
{
Console.WriteLine(sel.grade + "," + sel.name + "," + sel.scores.Max());
}
/*
3,Tom,80
3,Brain,70
4,Chris,80
5,James,100
*/
// 익명타입(새로운 형식)으로 표현 (이름 앞자만 표현)
var selectNew = students.Select(std => new { grd = std.grade, nm = std.name.Substring(0,1), max = std.scores.Max() });
foreach (var sel in selectNew)
{
Console.WriteLine(sel.grd + "," + sel.nm + "," + sel.max);
}
/*
3,T,80
3,B,70
4,C,80
5,J,100
*/
var selectMany = students.SelectMany((student, index) => student.scores.Select(score => index + ">" + score) );
foreach (var sel in selectMany)
{
Console.WriteLine(sel);
}
/*
0>60
0>80
1>50
1>70
2>80
2>80
3>100
3>100
*/
var selectmanyQuery = from student in students
from score in student.scores
select new { score, student };
foreach (var sel in selectmanyQuery)
{
Console.WriteLine(sel.score + ">" + sel.student.name);
}
/*
60>Tom
80>Tom
50>Brain
70>Brain
80>Chris
80>Chris
100>James
100>James
*/
// select 방법으로 selectMany와 동일하게 표현
var selectby = students.Select((student) => student.scores);
foreach (var sel in selectby)
{
foreach (var score in sel)
{
Console.WriteLine(score);
}
}
// 두요소를 순서대로 결합
var zip = teachers.Zip(students, (first, second) => new { first.grade, first.name, student = second.name });
foreach (var sel in zip)
{
Console.WriteLine(sel.grade + ", " + sel.name + ", " + sel.student);
}
/*
3, Miss Christina, Tom
4, Mr. Tayler, Brain
6, Mr. Jone, Chris
5, James, James
*/
요소
시퀀스에서 특정 단일 요소를 반환
ElementAt, ElementAtOrDefault, First, FirstOrDefault, Last, LastOrDefault, Single, SingleOrDefault
List<Student> emptyStudents = new List<Student>();
List<Student> students = new List<Student>
{
new Student{grade = 3, name = "Tom", scores = new int[] {60, 80} },
new Student{grade = 3, name = "Brian" , scores = new int[] {50, 70} },
new Student{grade = 4, name = "Chris" , scores = new int[] {80, 80}},
new Student{grade = 5, name = "James" , scores = new int[] {100, 100} },
};
var elementAt = students.ElementAt(1).name; /* Brian */
var elementAtException = students.ElementAt(5); // Elenemt가 없으면 ArgumentOutOfRangeException 예외 발생
var elementAtNull = students.ElementAtOrDefault(5); // Elenemt가 없으면 null 반환
var first = students.First().name; /* Tom */
var last = students.Last().name; /* James */
var firstDefault = emptyStudents.FirstOrDefault(); // null 반환
var lastDefault = emptyStudents.LastOrDefault(); // null 반환
var singleEmpty = emptyStudents.Single(); // 비어있는 요소 반환시 System.InvalidOperationException: 'Sequence contains more than one element'
var single = students.Single(); // 2개 이상 요소 반환시 System.InvalidOperationException: 'Sequence contains more than one element'
var singleDefaultEmpty = emptyStudents.SingleOrDefault(); // 비어있는요소는 null 을 반환
var singleDefault = students.SingleOrDefault( student=> student.grade==3); // 2개 이상 요소 반환시 System.InvalidOperationException: 'Sequence contains more than one element'
참고
https://learn.microsoft.com/ko-kr/dotnet/csharp/programming-guide/concepts/linq/projection-operations
https://learn.microsoft.com/ko-kr/dotnet/csharp/programming-guide/concepts/linq/element-operations
반응형