티스토리 뷰

프로그래밍

LINQ 정렬 기능 사용하기

야라바 2016. 10. 7. 11:02


 ※ LINQ 연관글 모음

 

SELECT * FROM tablea WHERE username like '%hong%' ORDER BY username, userid DESC;

위의 SQL 문장은 tablea라는 테이블에서 username 컬럼에 "hong"이 들어 있는 모든 행을 추출하면서 username 컬럼으로 오름차순 정렬하고 username 값이 같은 행끼리는 userid 컬럼 값으로 내림차순 정렬하는 질의문입니다. 데이터소스로 외부 데이터베이스 뿐만아니라 내부 자료형을 지정할 수 있는 LINQ에서도 정렬 기능을 적절하게 사용하여 효과적인 프로그래밍을 수행할 수 있습니다. 

Dictionary<string, string> user_names = new Dictionary<string, string>()
    { {"hong1", "홍길동"}, {"hongsun", "홍길순"}, {"parkms", "박문수"}, {"kimsg", "김삿갓" } };
Dictionary<string, int> user_ages = new Dictionary<string, int>() 
    { { "hong1", 23 }, { "hongsun", 32 }, { "parkms", 54 }, { "kimsg", 63 } };

var qry = user_names.Where(name => name.Key[0] == 'h')
            .OrderByDescending(name => name.Key).Select(name => new { name.Value, name.Key });

int i = 0;
foreach (var item in qry)
{
    Console.WriteLine(" {0} : {1} - {2}", ++i, item.Key, item.Value);
}
Console.WriteLine("-----------------------------");

var qry2 = from name in user_names
           orderby name.Key ascending
    select new { Id = name.Key, Name = name.Value };
int j = 0;
foreach (var item in qry2)
{
    Console.WriteLine(" {0} : {1} - {2}", ++j, item.Id, item.Name);
}

"LINQ 질의의 기본과 사전 타입"에서 언급한 것과 같이 LINQ 구문은 질의(Query) 문법과 메소드(Method) 문법으로 표현할 수 있습니다. 위의 코드에서 qry는 메소드 문법을 사용한 것으로 필터링하는 Where()다음에 "OrderBy" 또는 "OrderByDescending" 메소드를 활용하여 람다 구문으로 정렬 기준을 지정하면 됩니다. qry2는 질의 문법을 사용한 것으로 SQL 표현처럼 "orderby" 구문 다음에 정렬 기준을 기술하고 정렬 방법을 "ascending" 또는 "descending"으로 이어서 지정하거나 오름차순인 경우에는 정렬 방법을 지정하지 않아도 됩니다.


위의 그림은 위의 코드를 수행한 것으로 qry와 qry2의 차이를 비교해 보면 qry의 경우에는 Where 구문으로 필터링을 적용했는데 키의 첫문자가 'h'인 것만을 대상으로 으로 하도록 했습니다. 정렬 방법의 경우에는 qry는 내림차순 정렬했고 qry2는 오름차순으로 정렬했습니다.  또다른 차이점은 qry2의 경우에는 select 구문에서 질의 결과의 항목이름 대신 Id와  Name이라라는 별칭(alias)을 지정했다는 것입니다. 


var qry2 = from name in user_names
           orderby name.Key, name.Value descending
           select new { Id = name.Key, Name = name.Value };

var qry = user_names.Where(name => name.Key[0] == 'h')
            .OrderByDescending(name => name.Key).ThenBy(name => name.Value)
            .Select(name => new { name.Value, name.Key });


그렇다면, 글의 첫 예시로 기술한 SQL문장처럼 정렬 기준으로 여러 컬럼을 지정하려면 어떻게 해야 될까? 질의 문법의 경우에는 위의 예제의 qry2 처럼 SQL과 다르지 않습니다. 정렬 기준을 콤마(,)로 차례대로 기술하고 각 기준에는 ascending(생략 포함) 또는 descending 을 각각 지정할 수 있습니다.  메소드 문법의 경우에는 "ThenBy", "ThenByDescending" 메소드를 활용하여 2차, 3차등의 정렬 기준을 지정할 수 있으며 사용법은  "OrderBy" 또는 "OrderByDescending" 메소드와 같습니다.


public class MyComparer : IComparer
{
    public int Compare(string x, string y)
    {
        if (x[0] == y[0]) return 0;
        else if (x[0] > y[0]) return 1;
        else return -1;
    }
}

...

var qry = user_names.OrderByDescending(name => name.Key, new MyComparer())
            .ThenBy(name => name.Value, new MyComparer())
            .Select(name => new { name.Value, name.Key });
    

정렬을 수행하는 "ThenBy", "ThenByDescending", "OrderBy", "OrderByDescending" 메소드들은 람다 구문을 통해서 정렬 기준을 파라미터로 받아 항목간의 단순 비교를 통한 정렬을 수행하지만, 위의 예제 처럼 두번째 파라미터로 IComparer를 구현한 사용자 클래스를 전달해서 나름의 비교를 수행할 수 있습니다. IComparer를 구현하는 사용자 클래스에는 정수 값(0, 1, -1)을 리턴하는 Compare() 메소드를 작성해야 하는데 어떤 방식으로 비교하든 두 항목의 비교 결과를 1 또는 -1로 리턴하면 오름차순 또는 내림차순으로 정렬을 수행할 수 있습니다.


댓글
댓글쓰기 폼