컬렉션에서 KeyPaths 사용하기
키 경로를 기준으로 컬렉션을 정렬하고 매핑합니다.
컬렉션에서 KeyPaths 사용하기은(는) CoddyKit의 무료 Swift Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Swift Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Swift Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
컬렉션에서 빛나는 키 경로
map, sorted, filter와 같은 컬렉션 연산은 각 요소의 속성 하나만 읽는 경우가 많습니다. 키 경로를 사용하면 클로저를 작성하지 않고도 그 의도를 표현할 수 있습니다.
Swift는 단일 인수를 받아 값을 반환하는 함수가 필요한 곳이라면 어디서든 키 경로를 허용합니다. 키 경로를 Root에서 Value로 가는 함수로 사용할 수 있기 때문입니다.
struct Person {
let name: String
let age: Int
}
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let names = people.map(\.name)
print(names)키 경로를 사용한 map 축약형
map(\.property)를 전달하는 것은 해당 속성을 반환하는 클로저를 작성하는 것과 같지만, 더 짧고 명확합니다. 앞의 백슬래시와 점을 사용하면 컴파일러가 요소 형식을 추론할 수 있습니다.
아래의 두 형식을 비교해 보십시오. 두 형식은 같은 결과를 만듭니다.
struct Person {
let name: String
let age: Int
}
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let closureForm = people.map { $0.age }
let keyPathForm = people.map(\.age)
print(closureForm)
print(keyPathForm)키 경로 비교를 사용하는 sorted(by:)
속성을 기준으로 정렬하려면 여전히 짧은 비교 클로저를 작성해야 하지만, 그 안에서 키 경로를 통해 속성을 읽으면 코드가 더 명확해집니다.
여기서는 age 값을 비교하여 사람들을 가장 어린 사람부터 가장 나이 많은 사람 순서로 정렬합니다.
struct Person {
let name: String
let age: Int
}
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let path = \Person.age
let sorted = people.sorted { $0[keyPath: path] < $1[keyPath: path] }
print(sorted.map(\.name))재사용 가능한 정렬 도우미
어떤 배열이든 비교 가능한 임의의 속성을 기준으로 정렬하는 제네릭 도우미를 작성할 수 있으며, 해당 속성을 키 경로 인수로 전달합니다. 이렇게 하면 코드베이스 어디서든 필드를 기준으로 정렬하는 작업을 한 줄로 작성할 수 있습니다.
T: Comparable 제약은 해당 속성을 정렬할 수 있도록 보장합니다.
func sorted<E, T: Comparable>(_ array: [E], by path: KeyPath<E, T>) -> [E] {
array.sorted { $0[keyPath: path] < $1[keyPath: path] }
}
struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
print(sorted(people, by: \.age).map(\.name))키 경로를 통한 필터링
filter에는 불리언을 반환하는 조건식이 필요하므로, 속성이 이미 불리언인 경우에만 일반 속성 키 경로를 직접 사용할 수 있습니다.
여기서는 각 작업에 isDone 플래그가 있으며, 키 경로 축약형을 사용해 이를 기준으로 필터링합니다.
struct Task {
let title: String
let isDone: Bool
}
let tasks = [Task(title: "A", isDone: true), Task(title: "B", isDone: false)]
let finished = tasks.filter(\.isDone)
print(finished.map(\.title))불리언이 아닌 속성으로 필터링
불리언이 아닌 속성을 기준으로 필터링할 때는 클로저 안에서 키 경로를 통해 해당 속성을 읽고 비교해야 합니다. 제네릭 도우미를 사용하면 이 패턴을 모든 동일성 비교 가능한 속성에 적용할 수 있습니다.
여기서는 사람의 city가 지정한 값과 일치하는 경우만 남깁니다.
struct Person { let name: String; let city: String }
func filter<E, T: Equatable>(_ array: [E], _ path: KeyPath<E, T>, equals value: T) -> [E] {
array.filter { $0[keyPath: path] == value }
}
let people = [Person(name: "Ana", city: "Oslo"), Person(name: "Ben", city: "Rome")]
print(filter(people, \.city, equals: "Oslo").map(\.name))키 경로로 max 및 min 사용하기
max(by:)와 min(by:) 메서드는 sorted와 마찬가지로 비교 클로저를 받습니다. 키 경로를 통해 속성을 읽으면 가장 크거나 가장 작은 값을 가진 요소를 찾을 수 있습니다.
여기서는 가장 나이가 많은 사람을 찾습니다.
struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25), Person(name: "Cy", age: 41)]
let path = \Person.age
if let oldest = people.max(by: { $0[keyPath: path] < $1[keyPath: path] }) {
print(oldest.name)
}reduce로 속성 합산하기
map(\.property)와 reduce를 결합하면 숫자 필드의 합계를 구할 수 있습니다. 먼저 각 요소에서 원하는 숫자를 추출한 다음 모두 더합니다.
여기서는 하나의 파이프라인으로 모든 나이를 합산합니다.
struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let totalAge = people.map(\.age).reduce(0, +)
print(totalAge)키 경로로 그룹화하기
Dictionary(grouping:by:)는 클로저의 결과에 따라 요소를 묶습니다. 키 경로를 통해 속성을 읽어 해당 필드를 기준으로 그룹화할 수 있습니다.
여기서는 사람들을 city별로 배열 사전으로 그룹화합니다.
struct Person { let name: String; let city: String }
let people = [
Person(name: "Ana", city: "Oslo"),
Person(name: "Ben", city: "Rome"),
Person(name: "Cy", city: "Oslo")
]
let path = \Person.city
let byCity = Dictionary(grouping: people, by: { $0[keyPath: path] })
print(byCity["Oslo"]?.map(\.name) ?? [])여러 필드 기준으로 정렬하기
한 필드를 기준으로 정렬하고 다른 필드로 동률을 해소하려면, 먼저 기본 키 경로를 비교하고 기본 값이 같을 때 보조 키 경로를 사용합니다.
여기서는 나이를 기준으로 정렬한 다음, 나이가 같으면 이름을 기준으로 정렬합니다.
struct Person { let name: String; let age: Int }
let people = [
Person(name: "Zoe", age: 30),
Person(name: "Ana", age: 30),
Person(name: "Ben", age: 25)
]
let sorted = people.sorted {
if $0[keyPath: \Person.age] != $1[keyPath: \Person.age] {
return $0.age < $1.age
}
return $0.name < $1.name
}
print(sorted.map(\.name))여기서는 왜 키 경로가 클로저보다 나은가
컬렉션 호출에서 키 경로를 사용하면 반복적인 코드를 줄이고, 클로저 본문에 오타가 생길 가능성을 없애며, 단일 필드를 추출한다는 의도를 명확하게 드러낼 수 있습니다.
복잡한 변환에는 여전히 클로저가 적합하지만, 단순히 속성을 읽는 경우에는 \.property가 가장 명확한 선택입니다.
struct Product { let name: String; let price: Double }
let products = [Product(name: "Pen", price: 2), Product(name: "Pad", price: 5)]
let names = products.map(\.name)
let prices = products.map(\.price)
print(names)
print(prices)빠른 확인: map의 키 경로
각 요소에서 속성 하나를 추출할 때 사용할 간결한 키 경로 형식을 고르십시오.
복습: 컬렉션의 키 경로
키 경로를 사용하면 컬렉션 코드를 간결하게 작성할 수 있다는 것을 살펴보았습니다.
map(\.property)는 클로저 없이 단일 필드를 추출합니다.filter(\.boolProperty)는 불리언 필드에 직접 사용할 수 있으며, 그 외의 필드에는[keyPath:]를 사용하는 클로저를 작성합니다.- 정렬,
max,min은 비교 클로저 안에서 키 경로를 통해 속성을 읽습니다. KeyPath를 받는 제네릭 도우미를 사용하면 필드를 기준으로 정렬하고 필터링하는 작업을 재사용 가능한 한 줄 코드로 만들 수 있습니다.
다음에는 값을 읽기만 하는 것이 아니라 설정할 수 있게 해 주는 쓰기 가능한 키 경로를 배웁니다.
struct Person { let name: String; let age: Int }
let people = [Person(name: "Ana", age: 30), Person(name: "Ben", age: 25)]
let youngestFirst = people.sorted { $0[keyPath: \Person.age] < $1[keyPath: \Person.age] }
print(youngestFirst.map(\.name))자주 묻는 질문
“컬렉션에서 KeyPaths 사용하기” 강의는 무료인가요?
네 — “컬렉션에서 KeyPaths 사용하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Swift Academy 강의 전체를 잠금 해제할 수 있습니다. Swift Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“컬렉션에서 KeyPaths 사용하기”에서 뭘 배우나요?
키 경로를 기준으로 컬렉션을 정렬하고 매핑합니다. 브라우저에서 직접 실행하는 실습 코드로 Swift Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Swift Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Swift Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“컬렉션에서 KeyPaths 사용하기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Swift Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Swift Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- KeyPath 기초
- 컬렉션에서 KeyPaths 사용하기
- 쓰기 가능 및 참조 KeyPaths
- @dynamicMemberLookup