본문 바로가기
Apple/Swift

[Swift] 배열 정렬하기

by 어멘드 2022. 1. 13.
반응형

 알고리즘 문제를 풀다 보면 정렬이 되게 자주 필요한데, 매번 직접 구현하기는 번거롭다. Array에는 이미 O(NlogN)의 sort 메소드가 구현되어 있으니 이걸 쓰자.

 Array 공식문서로 가보면, 정렬 관련 메소드는 4개를 제공한다. 하나씩 자세히 살펴볼 건데, 일단 사용법만 빠르게 요약 먼저!

 


다시 공식 문서로 돌아와서, 4개의 정렬 메소드를 살펴보자. 두 가지 기준으로 둘둘씩 나눌 수 있는데

  1. 원본 배열 자체를 변경하느냐에 따라
    • 원본 자체를 변경 : sort(), sort(by:)
    • 원본은 두고 정렬된 새 배열을 리턴 : sorted(), sorted(by:)
  2. 정렬 기준을 어떤 방법으로 정의해주냐에 따라
    • Comparable 프로토콜 채택 : sort(), sorted()
    • (Element, Element) -> Bool 클로저로 전달 : sort(by:), sorted(by:)

 

 표로 정리하면 아래와 같다.

 


1.  sort와 sorted

 이름에서도 느낌이 오는데, sort는 원본 자체를 변경해버리고 sorted는 정렬 새 배열을 리턴한다.

 

 이렇게 originalArr.sorted()를 해도 originalArr은 정렬되지 않고 그대로이다. 그리고 "Result of call to 'sorted()' is unused"라는 경고 메시지가 뜬다. 정렬된 새 배열을 리턴해줬는데 이 리턴 값을 그냥 버렸기 때문이다.

 

 이렇게 리턴된 sortedArr를 담아서 출력해보면, 정렬되어있는 것을 확인할 수 있다.

 

 sorted말고 sort()를 해주니 originalArr이 정렬되었다. PS에서는 주로 sorted보다는 sort를 쓸 일이 많은 것 같다.

 

 sort를 사용할 때 주의할 점이 있는데, 배열 자체를 변경하는 것이기 때문에 mutable 컬렉션에 대해서만 쓸 수 있다. let으로 선언된 immutableArr에 대해 sort()를 하려고 하니 "Cannot use mutating member on immubale value"라는 에러가 뜬다.

 


2. ()와 (by:)

 제목이 이상한데...ㅠ 파라미터에 by라는 (Element, Element) -> Bool 클로저를 넘겨주는 것과 그렇지 않은 것을 말한 것이다. by는 정렬 기준이다.

 

 정렬을 직접 구현할 때를 생각해보면, 정렬은 두 요소를 비교하는 작업의 반복이다. 오름차순으로 정렬하는 상황이면, A와 B라는 수를 가지고 A가 B보다 작은가?라는 물음에 대해 참/거짓을 판별하게 된다. 저 물음이 바로 by 클로저이다!

 

 정수 두 개를 비교해서 앞에오는 정수가 더 작은지 여부를 리턴하는 클로저 ascending을 선언했다. 이것을 sort(by: ascending)에 넘겨주면, 이것을 비교 함수로 사용해 정렬을 해준다. 결과는 오름차순이 된다. 반대로 descending 클로저를 넘겨주면 내림차순 정렬이 된다.

 

 by로 정렬기준을 알려주지 않는 경우에는 어떻게 될까? 정렬을 하려면 두 엘리먼트를 비교를 해야 하는데, 비교 기준이 없는데??

 

 by가 없는 sort()나 sorted()를 사용하려면 Element가 Comparable 프로토콜을 채택한 타입이어야 하는 이유가 바로 이것이다. 공식 문서를 보면 sort()와 sorted()에는 "Available when Elemnt conforms to Comparable"이라고 적혀있다.

 

 Comparable 프로토콜은 이름 그대로 비교 가능한 타입이라는 뜻이다. 따라서 Comparable을 채택하면 < 오퍼레이터를 구현해야 하고, 이 < 연산자가 비교 기준이 된다.

 

 Comparable하지 않은 커스텀 타입을 하나 만들어보자. 이 Person 배열에 대해 sort()를 하려고 하니 "어쩌고저쩌고 requires that 'Person' conform to 'Comparable"이라는 에러가 뜬다. Person에 Comparable 프로토콜을 채택해줘야 sort()를 쓸 수 있다는 말!

 

 Person 클래스에 Comparable 프로토콜을 채택시켜줘 보자. < 연산자는 age를 기준으로 구현해줬다.

 이제 정렬이 잘 된다:)

반응형

댓글