1.map
1. normal
func map<T>(_ transform: (Self.Element) -> T) -> [T]
- Self.Element를 T로 변환하여 새로운 배열을 반환하는 역할을 한다.
- 즉, 배열의 원소를 원하는 타입으로 변환하여 새로운 배열을 만드는 것
let numbers = [1, 2, 3, 4]
let strings = numbers.map { "\($0)" }
print(strings) // ["1", "2", "3", "4"]
2. error handling
func map<T, E>(_ transform: (Self.Element) throws(E) -> T) throws(E) -> [T] where E : Error
- 일반적인 map과 달리 Error를 던질 수 있다.
- transform 클로져에서 Error를 던지면 map함수 자체에서도 Error를 던진다.
let invalidStrings = ["1", "two", "3"]
do {
let numbers = try invalidStrings.map { str -> Int in
guard let num = Int(str) else {
throw ConversionError.invalidNumber
}
return num
}
print(numbers)
} catch {
print("Conversion failed: \(error)") // Conversion failed: invalidNumber
}
2. flatMap
signature
func flatMap<SegmentOfResult>(
_ transform: (Self.Element) throws -> SegmentOfResult
) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence
사용 예시
let numbers = [1, 2, 3, 4]
// 맵
let mapped = numbers.map { Array(repeating: $0, count: $0) }
print(mapped)
// [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
//flatMap의 평탄화
let flatMapped = numbers.flatMap { Array(repeating: $0, count: $0) }
print(flatMapped)
// [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
Sequence Protocol
protocol Sequence {
associatedtype Element
associatedtype Iterator: IteratorProtocol //반복자
func makeIterator() -> Iterator
}
- 제네릭 타입
- SegmentOfResult
- Sequence 프로토콜을 준수해야 함
- Sequence 프로토콜
- Array, set, dictionary등의 컬렉션을 포함하고 반복가능(iterable) 할 수 있는 모든 타입을 정의하는 프로토콜이다.
- SegmentOfResult.Element
- Sequence의 요소 타입
- flatMap의 결과 배열의 요소 타입
- SegmentOfResult
- transform 클로져
- Self.Element(현재 배열의 요소)를 받아서 Sequence(배열, 리스트 등)를 반환하는 클로
- throws
- 이 클로져는 오류를 던질 수 도 있음
- rethrows
- transform 클로져가 오류를 던지면 rethrows도 오류를 던질 수 있고 오류를 던지지 않으면 rethrows도 오류를 던지지 않음
- throws는 항상 do-catch 필수
- rethrows는 상황에 맞게 do-catch 쓰거나 안쓰거나 가능
- 반환 값
- SegmentOfResult.Element 타입의 배열을 반환
- 변환된 결과가 중첩 배열이면 이를 평탄화 시켜 한 단일 배열로 변환한다.
- 이를 평탄화라고 한다.
3.CompactMap
func compactMap<T>(_ transform: (Element) throws -> T?) rethrows -> [T]
//맵을 사용했을 때
let strings = ["1", "two", "3", "four"]
let mapped = strings.map { Int($0) }
print(mapped)
// [Optional(1), nil, Optional(3), nil] → `[Int?]`
//compactMap을 사용했을 때
let compactMapped = strings.compactMap { Int($0) }
print(compactMapped)
// [1, 3] → `[Int]`
- nil이 포함될 수 있는 배열을 변환할 때 사용되며, nil 값을 자동으로 제거하여 새로운 배열을 반환하는 함수이다.
- map과 비슷하지만 변환된 결과가 nil일 경우 자동으로 제외하고 배열을 만들어준다.
4.reduce
1. reduce(_:_:)
func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult: (Result, Self.Element) throws -> Result
) rethrows -> Result
- initialResult : 초기값
- nextPartialResult : 누적 값을 업데이트 하는 클로져
- 최종 결과값을 반환
- 새로운 값을 반환
- 불변성
- 기존의 값이 변경되지 않음
- 불필요한 복사가 발생함
- 새로운 값 할당할때 사용하면 좋다.
- 불변성
let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(0) { partialResult, element in
partialResult + element
}
print(sum) // 15
//0 → (0 + 1) → (1 + 2) → (3 + 3) → (6 + 4) → (10 + 5) → 15
-
- 각 단계마다 partialResult가 새로운 값으로 갱신되어 불변성을 유지한다.
2. reduce(into:_:)
func reduce<Result>(
into initialResult: Result,
_ updateAccumulatingResult: (inout Result, Self.Element) throws -> ()
) rethrows -> Result
- initialResult : 초기값(inout으로 직접 변경)
- updateAccumulatingResult : 누적 값을 직접 변경하는 클로져(inout)
- 최종 결과값을 반환
- inout을 사용하여 기존 값을 직접 변경하기 때문에 reduce(_:_:) 보다 성능이 좋음
- 배열, 딕셔너리, 집합등 변경 가능한 데이터를 처리할 때 좋다.
let numbers = [1, 2, 3, 4, 5]
let sum = numbers.reduce(into: 0) { result, element in
result += element
}
print(sum) // 15
- reduce(into:_:)는 누적된 결과값을 변경 가능한 상태(inout)로 유지하므로, 불필요한 복사가 발생하지 않아 성능이 더 좋음
'swift' 카테고리의 다른 글
UIView의 draw(_:)는 그림을 그리는 함수이다. (0) | 2025.04.18 |
---|---|
[Swift] Combine (0) | 2025.02.28 |
[iOS] super.init(nibName: nil, bundle: nil) 이해하기 (0) | 2025.02.26 |
[iOS] NSCoder 생성 방법 (0) | 2025.02.26 |
[Swift] UserDefaults.synchronize() (0) | 2025.02.04 |