장난감 연구소

[C#] Array.Sort() 정렬 조건 바꾸기 본문

프로그래밍/C#

[C#] Array.Sort() 정렬 조건 바꾸기

changi1122 2019. 5. 15. 23:31

    Array.Sort()를 사용하면 오름차순으로 배열을 정렬할 수 있다. 그런데 프로그래밍하다 보면, 단순히 오름차순으로 정렬하는 것뿐만 아니라, 기준 항목이 같을 경우 두 번째 항목을 비교하는 등 복잡한 조건으로 정렬해야 할 때도 있다. 이 글에서는 이처럼 복잡한 조건으로 Array.Sort()를 사용해 정렬하는 방법을 다룬다.

    람다식 사용하기

    람다식은 C#에서 익명 메서드를 만드는 방법 중 하나이다. 대리자와 익명 메서드, 람다식에 대해서 알고 싶다면 링크의 두 글을 확인하기 바란다. #대리자 #무명 메서드와 람다식

    람다식에 대해 간단하게 설명하자면, "(매개변수 목록) => 식"의 형태로 표현되는 메서드이다. Array.Sort(배열, 람다식)의 형태로 배열 뒤에 적어주면 정렬할 때 사용된다. 아래 코드를 보자.

    int[] arr = { 4, 5, 2, 1, 3 };
    
    Array.Sort(arr, (a, b) => (a > b) ? -1 : 1);
    //arr : { 5, 4, 3, 2, 1 }

    Array.Sort()로 넘어간 람다식은 두 개의 요소를 비교할 때 사용된다. 람다식이 -1을 반환하면 a, b 순으로 정렬되고, 1을 반환하면 b, a 순으로 정렬된다. 위 예시 코드에서 arr은 내림차순으로 정렬된다. a가 b보다 클 때는 -1을 반환하여 a, b순이고, a가 b보다 작을 때는 1을 반환하여 b, a 순이기 때문이다.

    람다식을 응용하면 다양한 조건으로 정렬할 수 있다. 이번에는 문자열의 길이로 내림차순 정렬하면서, 길이가 같을 때 알파벳 내림차순으로 정렬해보자.

    string[] arr = { "abc", "AAANews", "cnn", "bbc", "foxnews" };
    
    Array.Sort(arr, (a, b) => {
        if (a.Length < b.Length)
            return -1;
        else if (a.Length > b.Length)
            return 1;
        else //a.Length == b.Length
            return String.Compare(a, b);
    });
    //String.Compare(a, b)는 알파벳 순으로 a가 빠를 때 -1, a가 느릴 때 1 반환
    //결과 arr : { "abc", "bbc", "cnn", "AAANews", "foxnews"}

    위 코드의 람다식에서 먼저 a의 길이가 짧으면 -1을 반환하고, a의 길이가 길면 1을 반환한다. a와 b의 길이가 같을 때는 String.Compare(a, b)를 반환한다. String.Compare()는 문자열 두 개를 비교할 때의 기본값인데, 알파벳 순으로 a가 빠를 때 -1, a가 느릴 때 1을 반환하게 된다.

    이 결과 첫 번째 기준으로 문자열의 길이, 두 번째 기준으로 문자열의 알파벳 순으로 정렬되는 것이 확인된다.

    객체의 해당 클래스에 CompareTo() 구현하기

    //Array.Sort 사용을 위해 IComparable을 상속받아야 한다.
    class Data : IComparable
    {
      public int data;
    
      public Data(int data) //생성자
      {
        this.data = data;
      }
    
      //IComparable 상속 시 CompareTo 메서드를 정의해야 한다.
      //this와 obj를 비교했을 때, this의 값이 작으면 -1을 반환하고, 크면 1을 반환한다.
      //Sort()에서 CompareTo()의 반환값을 기준으로 정렬하는데 이를 다양하게 응용 가능하다.
      //아래 코드는 data을 조건으로 정렬하는 코드이다.
      public int CompareTo(object obj)
      {
        if (data < (obj as Data).data)
          return -1;
        else 
          return 1; 
      }
    }
    
    class Program
    {
      static void Main(string[] args)
      {
        Data[] datas = new Data[10];
        for (int i = 0; i < 10; ++i)
          datas[i] = new Data(data);
    
        //정렬
        Array.Sort(datas);
        
      }
    }

    만약 정렬할 배열이 직접 구현한 객체들의 배열이라면 객체에 IComparable 인터페이스를 구현함으로써 원하는 정렬 기준을 사용할 수 있다. 직접 만든 클래스에 IComparable 인터페이스를 상속받고, CompareTo()를 정의하면, 정렬될 때 CompareTo()의 반환 값을 기준으로 자료형 배열을 정렬하게 된다.

    int CompareTo(object obj)의 반환은 람다식과 동일하다. this 객체가 obj 인자보다 앞으로 정렬되야 하면 -1을 반환하고, 뒤로 정렬되야하면 1을 반환하면 된다.

    728x90
    개 댓글