[C#] LIQN
이 글은 한빛미디어의 이것이 C#이다를 보고 헷갈리는 부분 위주로 정리한 글입니다.
LINQ
C#의 LINQ(Language Integrated Query)는 데이터에 대한 질의를 SQL처럼 간단하게 작성하도록 도와주는 기능이다.
데이터 질의 : 데이터에 대해 물어본다. 즉, 어떠한 데이터들을 물어보고 답변을 받는다.
다음과 같은 키워드들을 통해 질문을 할 수 있다. From : 어떤 데이터 집합에서 찾을 것인가? Where : 어떤 값의 데이터를 찾을 것인가? Select : 어떤 항목을 추출할 것인가.
class Man
{
public int age = 5;
public string name = "name";
}
class Program
{
static void Main(string[] args)
{
Man[] mans = {
new Man() {age = 5 ,name = "김철수"},
new Man() {age = 25 ,name = "방민호"},
new Man() {age = 20 ,name = "김태희"},
};
// LINQ
var newMans = from man in mans // mans 안에 있는 각 데이터로부터
where man.age > 6 // age가 6보다 큰 데이터를 골라
orderby man.age // age순으로 정렬하여
select man; // 객체 추출
foreach (Man man in newMans)
{
Console.WriteLine(man.name);
}
}
}
// 결과
// 김태희
// 방민호
LINQ의 기본
from절
모든 LINQ 쿼리식은 반드시 from으로 시작
해야한다.
쿼리식의 대상이 될 데이터 원본
과 데이터 원본 안에 들어있는 각 요소 데이터를 나타내는 범위 변수
를 from절에서 지정
해줘야 한다.
이때 데이터 원본은 IEnumerable<T> 인터페이스를 상속
받는 형식이여야만 한다.
IEnumeable
즉, 일반적인 컬렉션, 배열 등은 물론 가능하고 직접 IEnumerable을 상속해서 직접 만든 데이터 집합도 가능하다.
LINQ의 범위 변수와 foreach문의 반복 변수의 차이점 : foreach문의 반복 변수는 데이터 원본으로부터 데이터를 담아내지만, 범위 변수는 실제로 데이터를 담지는 않는다. 그래서 쿼리식 외부에서 선언된 변수에 범위 변수의 데이터를 복사해 넣는 다는가 하는 일은 할 수 없음.
from절은 다음과 같이 from 범위변수 in 데이터원본
의 형식으로 사용한다.
int[] num = { 1,2,3,4,5,6};
var result = from n in num // 범위변수 n , 데이터 원본 num
where n > 5
orderby n
select n;
where
where은 한마디로 필터 역할
을 하는 연산자이다. from 절이 데이터 원본으로부터 뽑아낸 범위 변수가 가져야 하는
조건을 where 연산자에 인수로 입력
하면 LINQ는 해당 조건에 부합하는 데이터만을 걸러냄
.
다음과 같은 데이터가 있다.
Man[] mans = {
new Man() {age = 5 ,name = "김철수"},
new Man() {age = 25 ,name = "방민호"},
new Man() {age = 20 ,name = "김태희"},
};
이러한 데이터를 where문을 이용하여 age가 6 이상인 데이터만 걸러낼 수 있다.
var newMans = from man in mans
where man.age > 6 // age가 6보다 큰 데이터를 걸러냄
orderby man.age
select man;
orderby
orderby는 데이터의 정렬을 수행하는 연산자이다. 바로 앞에서 where의 예제에 있는 orderby를 그대로 보면 age를 기준으로 오름차순 정렬을 함을 알 수 있다.
var newMans = from man in mans
where man.age > 6
orderby man.age // age 기준으로 오름차순 정렬
select man;
기본적으로 오름차순 정렬이 기본이지만 명확하게 하기위해 또는 내림차순 정렬을 하기 위해 키워드를 명시할 수 있다.
var newMans = from man in mans
where man.age > 6
orderby man.age ascending // 내림자순은 descending
select man;
select
select 절은 최종 결과를 추출하는 쿼리식의 마침표
같은 존재이다.
LINQ의 질의 결과는 IEnumerable
Man[] mans = {
new Man() {age = 5 ,name = "김철수"},
new Man() {age = 25 ,name = "방민호"},
new Man() {age = 20 ,name = "김태희"},
};
var newMans = from man in mans
where man.age > 6
orderby man.age ascending
select man; //IEnumerable<Man>
//select man.age 라면 IEnumerable<int> select man.name 이라면 IEnumerable<string>
이뿐 아니라 select문은 무면 형식을 이용해서 즉석에서 새로운 형식을 만들 수도 있다.
var newMans = from man in mans
where man.age > 6
orderby man.age ascending // 내림자순은 descending
select new {Name = man.name, Age = man.age};
여러 개의 데이터 원본에 질의하기
여러 개의 데티어 원본에 접근하기 위해 from절을 중첩
하여 사용한다.
class Class
{
public int[] score;
public string name = "name";
}
class Program
{
static void Main(string[] args)
{
Class[] arrClass =
{
new Class(){name = "1반", score = new int[]{ 26,56,23,45} },
new Class(){name = "2반", score = new int[]{ 80,90,97,85} },
new Class(){name = "3반", score = new int[]{ 55,88,60,40} },
new Class(){name = "4반", score = new int[]{95,20,100,99} }
};
var goodClasses = from c in arrClass
from s in c.score // c안에 score에 접근
where s > 80 // s가 80이상이면
orderby s descending
select new{name = c.name, score = s}; // 조건에 맞는 데이터의 name과 score 추출
foreach (var c in goodClasses)
{
Console.WriteLine($"반 {c.name}, 점수 : {c.score}");
}
}
}
// 결과
//반 4반, 점수 : 100
//반 4반, 점수 : 99
//반 2반, 점수 : 97
//반 4반, 점수 : 95
//반 2반, 점수 : 90
//반 3반, 점수 : 88
//반 2반, 점수 : 85
group by로 데이터 분류하기
group by 절은 다음의 형식으로 사용함
group A by B into C
A에는 from절에서 뽑아낸 범위 변수
를, B에는 분류 기준
을, C에는 그룹 변수를 위치시키면 된다.
다음은 예시이다.
class Man
{
public int age;
public string name;
}
class Program
{
static void Main(string[] args)
{
Man[] mans = {
new Man() {age = 5 ,name = "김철수"},
new Man() {age = 25 ,name = "방민호"},
new Man() {age = 20 ,name = "김태희"},
new Man() {age = 25 ,name = "정우성"},
};
var newMans = from man in mans
orderby man.age
group man by man.age > 19 into g
select new {GroupKey = g.Key, mans = g};
// GroupKey로 분류 조건에 따른 true나 false를, mans로 그룹변수를 추출한다.
foreach (var Group in newMans)
{
Console.WriteLine(Group.GroupKey ? "성인" : "미성년자");
foreach (var g in Group.mans)
{
Console.WriteLine($">>> {g.name}, {g.age}");
}
}
}
}
// 결과
//미성년자
//>>> 김철수, 5
//성인
//>>> 김태희, 20
//>>> 방민호, 25
//>>> 정우성, 25
두 데이터 원본을 연결하는 join
join은 각 데이터 원본에서 특정 필드의 값
을 비교하여 일치하는 데이터끼리 연결
한다.
내부 조인
첫 번째 데이터 원본과 두 번쨰 데이터 원본의 특정 필드를 비교해서 일치하는 데이터를 반환. 이떄 기준은 첫 번째 원본 데이터이다.
from a in A
join b in B on a.XXXX equals b.YYYY
a는 from 절에서 뽑아낸 범위 변수
, 연결 대상 데이터 b 는 join 절에서 뽑아낸 변수
이다.
join 절의 on 키워드는 조인 조건
을 수반한다. 이때 on 절의 조건은 동등 Equality
만 허용된다.
~보다 작음, ~보다 큼 같은 비교 연산은 불가능
하다. 또한 == 연산자가 아닌 equals 라는 키워드를 이용
한다.
댓글남기기