티스토리 뷰

프로그래밍

LINQ 사용법 - 변환 및 생성

야라바 2016. 12. 20. 15:19


 ※ LINQ 연관글 모음

 

"LINQ 질의의 기본과 사전 타입"에서 다룬것과 같이 LINQ 질의의 수행시점에 따라 즉시 실행(Immediate Execution)과 지연 실행으로 나뉘어 질 수 있습니다. 질의를 선언만 하고 이후에 foreach 문장에서 실질적으로 실행하는 일반적인 지연 실행과 달리 질의 결과를 직접 받는 경우는 대부분 질의에 ToList(), First(), FirstOrDefault(), Last(), LastOrDefault()등의 메소드를 호출하는 방식을 사용하는데 이렇게 즉시 실행 방법에 사용하는 메소드 호출은 질의 선언 시점에 바로 실행하지 않더라도 질의 결과를 배열이나 리스트, 사전 형태로 변환하는데 사용할 수 있습니다.

■ 배열, 리스트, 사전으로 변환하기

List<Userinfo> userinfo = new List<Userinfo>() {
    new Userinfo { UserID = "hong1", UserName = "홍길동", UserType = "vip", Age = 50, Sex = true},
    new Userinfo { UserID = "parkms", UserName = "박문수", UserType = "vip", Age = 54, Sex = true},
    new Userinfo { UserID = "hongsun", UserName = "홍길순", UserType = "vvip", Age = 43, Sex = false},
    new Userinfo { UserID = "kimsg", UserName = "김삿갓", UserType = "general", Age = 35, Sex = true},
    new Userinfo { UserID = "hwang1", UserName = "황금복", UserType = "general", Age = 29, Sex = false},
    new Userinfo { UserID = "hwangso", UserName = "황소", UserType = "vip", Age = 63, Sex = true},
    new Userinfo { UserID = "kimsan", UserName = "김산", UserType = "general", Age = 23, Sex = true},
    new Userinfo { UserID = "seohee", UserName = "서희", UserType = "vvip", Age = 22, Sex = false}};

var qry = from ui in userinfo 
          select new { ui.UserName };

var usernames = qry.ToArray();
Console.WriteLine(" Total count : {0}, last name : {1}", usernames.Length, usernames.Last().UserName);

var userlist = qry.ToList();
Console.WriteLine(" Total count : {0}, first name : {1}", userlist.Count, userlist.First().UserName);

var qry2 = from ui in userinfo select ui;
var userdic = qry2.ToDictionary(u => u.UserID);
Console.WriteLine(" Total count : {0}, hong1's type : {1}", userdic.Count, userdic["hong1"].UserType);

ToArray()는 질의 결과를 배열로 변환하고 ToList()는 질의 결과를 리스트 형태로 변환합니다. 사전 형태로 변환하는 ToDictionary()를 호출할 경우에는 키로 사용할 항목을 위의 예제처럼 지정하면 키값을 통해서 빠르게 사전 오브젝트를 검색할 수 있습니다.

■ 원래 결과를 반대 순서로 가져오기

var qry = from ui in userinfo
          orderby ui.UserName
          select ui;

int i = 0;
foreach (var itm in qry)
{
    Console.WriteLine(" {0} : {1} {2} {3} ", ++i, itm.UserName, itm.UserID, itm.Age);
}
Console.WriteLine("---------------------");
i = 0;
foreach (var itm in qry.Reverse())
{
    Console.WriteLine(" {0} : {1} {2} {3} ", ++i, itm.UserName, itm.UserID, itm.Age);
}

통상 질의 결과를 정렬하는 것은 orderby 구문을 사용합니다.("LINQ 정렬 기능 사용하기" 참조) 그런데, 해당 질의 결과를 뒤집으려면 "ascending" 또는 "descending" 같은 구문을 질의에 추가해야 겠지만 질의 선언은 수정하지 않으면서도 결과를 변환하는 방법이 바로 Reverse() 메소드 입니다. 원래 질의의 정렬 방법과 무관하게 순서를 뒤집어서 출력해 줍니다.

■ 상수의 범위 및 반복값 만들기

var numbers = Enumerable.Range(-1, 5);
foreach (var itm in numbers)
{
    Console.WriteLine(" {0} ", itm);
}
Console.WriteLine("----------");

var nums = Enumerable.Repeat(5, 5);
foreach (var itm in nums)
{
    Console.WriteLine(" {0} ", itm);
}

Range()와 Repeat() 메소드는 질의의 일부라기 보다는 질의에 사용하기 위한 상수 오브젝트를 생성할 때 사용합니다. Range(시작 정수값, 개수), Repeat(값, 반복 개수)의 형태로 사용하고 정수 리스트 형태로 출력합니다.

■ 결과 합치기(붙이기) 및 비교

var qry = from ui in userinfo
          where ui.Age >= 50 && ui.Sex == true
          select new { ui.UserName, ui.Age, ui.Sex };
var qry2 = from ui in userinfo
           where ui.Age < 50 && ui.Sex == false
           select new { ui.UserName, ui.Age, ui.Sex };
var qry3 = from ui in userinfo
           where (ui.Age < 50 && ui.Sex == false) || (ui.Age >= 50 && ui.Sex == true)
           select new { ui.UserName, ui.Age, ui.Sex };
var allrst = qry.Concat(qry2);

foreach(var itm in allrst) 
{
    Console.WriteLine(itm); 
}

Console.WriteLine("qry+qry2 == qry3 : {0}", allrst.SequenceEqual(qry3));
Console.WriteLine("qry+qry2 == qry3(orderby) : {0}", 
    allrst.OrderBy(r => r.UserName).SequenceEqual(qry3.OrderBy(r => r.UserName)));

Concat()는 두 결과를 합쳐서(단순이 붙임) 새로운 결과를 생성하는 메소드입니다. 위의 예제에서 allrst는 qry와 qry2를 합친 결과이지만 두 질의를 or(||) 연산자로 통합시킨 qry3 질의와 SequenceEqual() 메소드로 비교하면 동일하지 않다는 결과가 나옵니다. 그 이유는 qry 질의 결과와 qry2 질의 결과를 합쳤기 때문에 한번에 필터링한 qry3와는 항목의 개수와 내용은 같지만 그 순서가 다르기 때문입니다. 그래서 그 결과를 재정렬해서 비교하면 동일하다는 결과가 나오는 것입니다. SequenceEqual() 메소드는 두 결과가 순서와 내용에 있어 완전히 일치하는지를 검사합니다.


댓글
댓글쓰기 폼