개발/Swift
Swift에서 정렬: sort vs sorted
까칠코더
2025. 11. 11. 13:47
반응형
Swift에서 정렬: sort vs sorted
Swift에서 배열을 정렬할 때 자주 혼동되는 두 메서드가 있습니다.
- sort(): 제자리(in‑place) 정렬 (자체 변경)
- sorted(): 새 배열을 반환 (원본 보존)
1. 핵심 요약
| 항목 | sort | sorted |
| 반환값 | 없음 (Void) | 새로 정렬된 [T] 반환 |
| 원본 변경 여부 | 변경됨 (in‑place) | 변경되지 않음 |
| 메모리 사용 | 덜 함 (in‑place) | 새 복사본 생성 → 더 큼 |
| 안정성 | Swift 5+ 부터 안정 정렬(stable) | 동일 |
| 사용 시점 | 임시 복사 불필요, 바로 수정할 때 | 원본 유지해야 할 때 |
| 가독성 | 명령형(sort()) | 함수형(sorted()) |
| 일반적 시간복잡도 | O(n log n) (TimSort 기반) | O(n log n) (동일 알고리즘) |
요약:
- 정렬된 배열이 필요하면 → sorted()
- 원본을 그대로 유지할 필요 없고, 제자리 정렬로 메모리 절약 → sort()
2. 기본 사용 예제
var numbers = [3, 1, 4, 1, 5]
numbers.sort()
print(numbers) // [1, 1, 3, 4, 5]
let sortedCopy = numbers.sorted()
print(sortedCopy) // [1, 1, 3, 4, 5]
print(numbers === sortedCopy) // false (서로 다른 배열)
- sort() 는 배열 자체가 바뀜
- sorted() 는 원본은 그대로 두고 복사본 반환
3. 커스텀 기준 정렬
3.1 오름차순 / 내림차순
let nums = [3, 1, 4, 1, 5]
let asc = nums.sorted(by: <) // [1, 1, 3, 4, 5]
let desc = nums.sorted(by: >) // [5, 4, 3, 1, 1]
3.2 클로저를 직접 전달
var people = ["Kim", "Lee", "Park"]
people.sort { $0.count < $1.count } // 길이 순 정렬
print(people) // ["Kim", "Lee", "Park"]
클로저 { $0 < $1 } 은 비교 연산자 함수 < 와 동등합니다.
4. 안정 정렬(Stable Sort)
Swift 5 이후 sort() 와 sorted() 모두 stable sort 입니다.
즉, 동일 비교 결과의 요소는 원래 순서를 유지합니다.
struct Item { let id: Int; let priority: Int }
var items = [
Item(id: 1, priority: 2),
Item(id: 2, priority: 2),
Item(id: 3, priority: 1)
]
items.sort { $0.priority < $1.priority }
print(items.map(\.id)) // [3, 1, 2] → id 1,2 의 상대 순서 유지됨
5. sort(by:) 와 sorted(by:) 차이 예제
var data = [3, 1, 4, 1, 5]
// 제자리(in-place) 정렬
data.sort(by: >)
print(data) // [5, 4, 3, 1, 1]
// 원본 유지 + 정렬 결과 새로 반환
let newData = data.sorted(by: <)
print(data) // [5, 4, 3, 1, 1]
print(newData) // [1, 1, 3, 4, 5]
sort(by:) 는 mutating 메서드 → 구조체(Array)의 값 자체가 변경됩니다.
6. 실무 패턴별 예제
6.1 정렬 결과를 UI/출력용으로만 쓸 때
let display = logs.sorted { $0.date > $1.date }
tableView.reload(with: display)
6.2 원본 배열 자체를 업데이트할 때
messages.sort { $0.timestamp > $1.timestamp }
6.3 문자열 길이, 대소문자 무시 정렬
let names = ["kim", "Park", "lee"]
let sortedInsensitive = names.sorted {
$0.caseInsensitiveCompare($1) == .orderedAscending
}
6.4 Optional 속성 비교 (nil 마지막)
struct User { let name: String; let score: Int? }
var users = [
User(name: "A", score: nil),
User(name: "B", score: 80),
User(name: "C", score: 50)
]
users.sort {
switch ($0.score, $1.score) {
case let (l?, r?): return l > r // 둘 다 값 있음
case (nil, _?): return false // nil 은 뒤로
case (_?, nil): return true
default: return false
}
}
6.5 복수 기준 정렬 (다중 키)
let students = [
("Kim", 2), ("Lee", 1), ("Park", 2), ("Choi", 3)
]
let sortedStudents = students.sorted {
if $0.1 == $1.1 { return $0.0 < $1.0 } // 1순위 동점 → 이름순
return $0.1 < $1.1 // 1순위: 학년
}
print(sortedStudents)
// [("Lee",1),("Kim",2),("Park",2),("Choi",3)]
7. 성능 비교
| 방법 | 메모리 사용 | 원본 변경 | 복사 오버헤드 | 비고 |
| sort() | 낮음 | O(1) 공간 | 없음 | in-place |
| sorted() | 높음 | 없음 | 새 배열 복사 | functional |
| reversed() vs reverse() | 동일 관계 (reverse() in-place) | 동일 | 동일 |
예제:
import Foundation
let data = (0..<1_000_00).map { _ in Int.random(in: 0..<1_000_00) }
var a = data
func measure(_ name: String, _ body: () -> Void) {
let t1 = CFAbsoluteTimeGetCurrent(); body(); let t2 = CFAbsoluteTimeGetCurrent()
print(name, ":", t2 - t1, "sec")
}
measure("sort") { a.sort() }
measure("sorted") { _ = data.sorted() }
일반적으로 sort() 가 약간 더 빠르고 메모리 효율적입니다.
하지만 둘 다 TimSort 기반으로 O(n log n) 이므로, 대부분의 경우 차이는 미미합니다.
8. 안정성(stability) 테스트 예제
struct Pair { let key: Int; let value: Int }
var pairs = [
Pair(key: 1, value: 10),
Pair(key: 2, value: 20),
Pair(key: 1, value: 30)
]
pairs.sort { $0.key < $1.key }
print(pairs.map(\.value)) // [10, 30, 20] → 같은 key(1)의 순서 유지
9. 흔한 실수와 교정
| 실수 | 교정 |
| let sorted = items.sort() → sorted가 Void | let sorted = items.sorted() |
| sort() 후 원본 보존 기대 | sorted() 사용해야 함 |
| sort(by: <) 과 sorted() 혼동 | sort는 mutating, sorted는 반환 |
| 대소문자 구분 안 한 문자열 정렬에서 < 사용 | caseInsensitiveCompare 사용 |
10. 참조 링크
- Array.sort()
https://developer.apple.com/documentation/swift/array/1538768-sort - Array.sorted(by:)
https://developer.apple.com/documentation/swift/array/1538769-sorted - String.caseInsensitiveCompare(_:)
https://developer.apple.com/documentation/foundation/nsstring/1407739-caseinsensitivecompare
11. 결론
- 원본 유지가 필요 → sorted() (함수형)
- 원본 수정이 허용 → sort() (명령형, 메모리 효율적)
- 복사 오버헤드 최소화가 목표면 sort()
- 불변 데이터 흐름 / 함수형 스타일에는 sorted()
- 둘 다 안정 정렬(TimSort 기반) 로, 결과 품질은 동일합니다.
반응형