Select
Select 절은 입력 시퀀스를 원하는 출력 시퀀스로 변환합니다.
Select 절
입력 시퀸스에 1을 더하여 출력 시퀀스를 만듭니다.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var numsPlusOne = from n in numbers
select n + 1;
// numsPlusOne = { 6, 5, 2, 4, 10, 9, 7, 8, 3, 1 };
하나의 속성만 선택하기
products 객체로 이루어진 입력 시퀀스에서 ProductName 속성으로 출력 시퀀스를 만듭니다.
List<Product> products = GetProductList();
var productNames = from p in products
select p.ProductName;
다른 타입으로 출력 바꾸기
numbers 배열을 활용해 문자로 표현된 숫자 출력 시퀀스를 만듭니다.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var textNums = from n in numbers
select strings[n];
// textNums = { "five", "four", "one", "three", "nine", "eight", "six", "seven", "two", "zero" };
출력에 익명 형식 활용하기
입력 시퀀스를 Select 절에서 new 생성자를 활용해 Upper 속성과 Lower 속성을 가진 익명 형식의 출력 시퀀스를 생성합니다.
string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
var upperLowerWords = from w in words
select new { Upper = w.ToUpper(), Lower = w.ToLower() };
// upperLowerWords = {
// { APPLE, apple },
// { BLUEBERRY, blueberry },
// { CHERRY, cherry },
// }
익명 형식을 활용하면 불필요한 클래스 생성을 줄일 수 있습니다.
C# 7.0 버전부터 Tuple 로도 출력을 투영할 수 있습니다. 출력은 System.ValueTuple 형식을 가진 System.Collections.IEnumerable 시퀀스가 됩니다.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var digitOddEvens = from n in numbers
select (Digit : strings[n], Even : (n % 2 == 0));
// digitOddEvens = {
// [ Digit : "five", Even : false ],
// [ Digit : "four", Even : true ],
// [ Digit : "one", Even : false ],
// ...
// }
새로운 타입 생성하기
익명 형식을 활용하여 새로운 타입으로 출력을 투영합니다.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var digitOddEvens = from n in numbers
select new { Digit = strings[n], Even = (n % 2 == 0) };
// digitOddEvens = {
// { Digit = "five", Even = false },
// { Digit = "four", Even = true },
// { Digit = "one", Even = false },
// ...
// }
익명 형식으로 새로운 타입을 생성할 수 있지만, C# 7.0 이후부터는 튜플 형식을 활용하는게 언어적인 이점이 많으니 참고바랍니다.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var digitOddEvens = from n in numbers
select (Digit : strings[n], Even : (n % 2 == 0));
속성 집합으로 출력 생성하기
Product 객체의 속성 중 ProductName, Category, UnitPrice 속성으로 출력 시퀀스를 만듭니다. 특히 UnitPrice 속성을 Price 로 이름을 변경하여 출력 시퀀스를 만들 수도 있습니다.
List<Product> products = GetProductList();
var productInfos = from p in products
select (p.ProductName, p.Category, Price : p.UnitPrice);
인덱스를 활용해 출력 만들기
numbers 배열의 속성 중 하나인 index 속성을 Select 절에 활용하여 숫자가 자신의 순서에 맞는 위치에 있는지를 확인할 수 있는 출력 시퀀스를 만듭니다.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var numsInPlace = numbers.Select((num, index) => (Num : num, InPlace : (num == index)));
// numsInPlace = {
// [ Num : 5, InPlace : false ],
// [ Num : 4, InPlace : false ],
// [ Num : 1, InPlace : false ],
// [ Num : 3, InPlace : true ],
// ...
// }
Select 절과 Where 절을 같이 활용하기
Select 절과 Where 절을 활용해서 5 이하의 숫자만 출력하는 시퀀스를 만듭니다.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var lowNums = from n in numbers
where n < 5
select digits[n];
// lowNums = { "four", "one", "three", "two", "zero" };
여러 입력 시퀀스로부터 하나의 출력 시퀀스 만들기
from 절로 numbersA 배열과 numbersB 배열을 입력 시퀀스로 받아 pairs 라는 하나의 출력 시퀀스를 만들 수 있습니다.
int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };
var pairs = from a in numbersA
from b in numbersB
where a < b
select (a, b);
// pairs = {
// [ 0, 1 ], [ 0, 3 ], [ 0, 5 ], [ 0, 7 ], [ 0, 8 ],
// [ 2, 3 ], [ 2, 5 ], [ 2, 7 ], [ 2, 8 ],
// [ 4, 5 ], [ 4, 7 ], [ 4, 8 ],
// ...
// }
서로 연관있는 입력 시퀀스로부터 하나의 출력 시퀀스 만들기
customers 리스트와 customers의 속성인 Orders를 입력 시퀀스로 받아, 500 이하인 order 만 모은 출력 시퀀스를 만듭니다.
List<Customer> customers = GetCustomerList();
var orders = from c in customers
from o in c.Orders
where o.Total < 500.00M
select (c.CustomerID, o.OrderID, o.Total);
1998.01.01 이후 주문만 모은 출력 시퀀스를 만듭니다.
List<Customer> customers = GetCustomerList();
var orders = from c in customers
from o in c.Orders
where o.OrderDate >= new DateTime(1998, 1, 1)
select (c.CustomerID, o.OrderID, o.OrderDate);
여러 Where 절을 활용해 입력 시퀀스를 제한한 특정한 출력 시퀀스를 만들 수도 있습니다.
아래 예제는 고객 중 WA 지역에 살면서 1997.01.01 d이후 주문만 출력하는 시퀀스를 만듭니다.
List<Customer> customers = GetCustomerList();
DateTime cutoffDate = new DateTime(1997, 1, 1);
var orders = from c in customers
where c.Region == "WA"
from o in c.Orders
where o.OrderDate >= cutoffDate
select (c.CustomerID, o.OrderID);
SelectMany 절
아래 예제는 처음 LINQ 를 사용하는 초보자에게 이해하기 어렵습니다. '이런 사용 방법도 있구나'하고 넘어가시면 되겠습니다.
List<Customer> customers = GetCustomerList();
var customerOrders =
customers.SelectMany(
(cust, custIndex) =>
cust.Orders.Select(o => "Customer #" + (custIndex + 1) +
" has an order with OrderID " + o.OrderID));
'Develop > .NET 가이드' 카테고리의 다른 글
[C#] LINQ 사용방법 - 정렬 연산자 OrderBy, ThenBy, OrderByDescending, ThenByDescending (0) | 2020.02.01 |
---|---|
[C#] LINQ 사용방법 - 분할 연산자 Take, Skip, TakeWhile, SkipWhile (0) | 2020.02.01 |
[C#] LINQ 사용방법 - Where (0) | 2019.12.03 |
[C#] Attributes 특성 (0) | 2019.11.29 |
[C#] Delegates 대리자와 Events 이벤트 중 선택하기 (0) | 2019.11.29 |
꾸준히 노력하는 개발자 "김예건" 입니다.