Notice
Recent Posts
Recent Comments
Link
大器晩成
고차함수 본문
고차함수란?
- 함수를 파라미터로 사용하거나, 함수의 실행 결과를 함수로 리턴하는 함수를 말합니다.
- 일반적으로 함수형 언어를 지향하는 언어들에 기본적으로 구현되어 있으며, 크게 3가지가 있습니다.
- map / filter / reduece (참고: forEach, compactMap, flatMap)
- Sequence, Collection 프로토콜을 따르는 컬렉션(배열, 딕셔너리, 세트 등)에 기본으로 구현되어 있습니다.
- Optional 타입에도 구현되어 있습니다.
1. map
- 기존의 배열 등의 각 아이템을 새롭게 매핑해서 새로운 배열을 리턴하는 함수입니다.
- 각 아이템을 매핑/변형해서 새로운 배열을 만들 때 사용합니다.
- 리턴 타입은 어떤 타입으로든 가능합니다.
// 예제 1
let numbers = [1, 2, 3, 4, 5]
var numbersString = numbers.map { num in
return "numbers의 숫자: \(num)"
}
print(numbersString)
//["numbers의 숫자: 1", "numbers의 숫자: 2", "numbers의 숫자: 3", "numbers의 숫자: 4", "numbers의 숫자: 5"]
// 예제 2
let square = numbers.map {
return $0 * $0
}
print(square) // [1, 4, 9, 16, 25]
// 예제 3
let alphabet = ["A", "B", "C", "D", "E", "F"]
let dobleAlphabed = alphabet.map {
return $0 + $0
}
print(dobleAlphabed) // ["AA", "BB", "CC", "DD", "EE", "FF"]
2. filter
- 기존 배열 등의 각 아이템의 조건을 확인 후 참을 만족하는 아이템을 걸러내서 새로운 배열을 리턴합니다.
- 각 아이템을 필터링해서 새로운 배열을 만들 때 사용합니다.
// 예제 1
let nubmer = [1, 2, 3, 4, 5, 6]
let even = nubmer.filter {
return $0 % 2 == 0
}
print(even) // [2, 4, 6]
// 예제 2
func isOdd(_ i: Int) -> Bool {
return i % 2 != 0
}
let odd = numbers.filter(isOdd) // 클로저가 아닌 함수로 전달해도 가능
print(odd)
// 예제 3
let names = ["Jobs", "Tim", "Young"]
var name = names.filter {
return $0.contains("Y") // 해당 문자에 Y가 포함되어있으면 참 아니면 거짓
}
print(name)
다중 filter
// 예제 1
let evenNumber2 = numbers.filter {
$0 % 2 == 0
}.filter {
$0 < 5
}
print(evenNumber2) //[2,4]
// 예제 2
let evenSquare = numbers.filter {
$0 % 2 == 0
}.map {
$0 * $0
}
print(evenSquare) //[4, 16, 36]
- 필터 함수를 연속으로 사용할 수도 있습니다.
- 위의 경우에 짝수를 먼저 판단 후, 나온 배열을 다시 필터를 통해 5보다 작은 값만 리턴하는 형태로 구성되어 있습니다.
- map 함수랑도 같이 사용할 수 있습니다.
3. reduce
- 기본 배열 등의 각 아이템을 클로저가 제공하는 방식으로 결합해서 마지막 결과값을 리턴
- 각 아이템을 결합해서 단 하나의 값으로 리턴할 때 사용합니다.
//기본 형태는 다음과 같이 구성되어있습니다.
let num = numbers.reduce(initrialREsult) { nextResult, 배열의 값 in
return nextResult + 배열의 값
}
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// reduce(초기값) // 초기값, // second 배열의 값
let num = numbers.reduce(0) { first, second in
print("first = \(first) + second = \(second)")
return first + second
}
print(num)
first = 0 + second = 1
first = 1 + second = 2
first = 3 + second = 3
first = 6 + second = 4
first = 10 + second = 5
first = 15 + second = 6
first = 21 + second = 7
first = 28 + second = 8
first = 36 + second = 9
first = 45 + second = 10
55
- 처음 초기값이 First라는 변수에 들어오며, 이후 return 된 값은 다시 초기값으로 설정됩니다. second는 배열의 값입니다.
- 동작은 확인해 보면 처음 사이클에서는 0 + 1, 1 + 2, 3 + 4 .... 45 + 10의 순서로 동작하게 됩니다.
// 예제 1
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let num = numbers.reduce(100) { $0 - $1}
print(num) // 45
// 예제 2
let numString = numbers.reduce("0") { $0 + String($1) }
print(numString) // 012345678910
- 초기값 기준으로 빼는 것도 가능합니다.
- 문자열로 리턴하는 것도 가능합니다.
여러 개의 고차함수 활용
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let evenSquareSum = numbers.filter { $0 % 2 == 0}
.map { $0 * $0}
.reduce(0) { $0 + $1 }
print(evenSquareSum) // 220
- 고차함수를 조합해서 다양하게 사용하는 것도 가능합니다.
4. forEach
- 기존 배열 등의 각 아이템을 활용해서 아이템 별로 특정 작업을 실행
- 각 아이템을 활용해서 각각 특정 작업을 실행할 때 사용
- forEach는 반환타입이 Void입니다.
let immutableNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
immutableNumbers.forEach {
print($0)
}
// 실제 앱에서 사용방식
[a, b, c, d].forEach {
view.addSubView($0)
}
- 실제 앱에서는 위와 같이 사용하는 경우도 종종 있습니다.
5. compactMap
- 기존 배열 등의 각 아이템을 새롭게 매핑해서 변형하되, 옵셔널 요소는 제거하고 새로울 배열을 리턴합니다.
- map + 옵셔널 제거
- 옵셔널 바인딩의 기능까지 내장
let numbers: [Int?] = [1, nil, nil, 3, 4, 5]
let newNumber = numbers.compactMap { $0 }
print(type(of: newNumber), newNumber) // Array<Int> [1, 3, 4, 5]
// compactMap를 사용하는것과 동일
let newNumber2 = numbers.filter { $0 != nil } .map { $0!}
print(newNumber2)
6. flatMap
- 중첩된 배열의 각 배열을 새롭게 매핑해서 내부 중첩된 배열을 제거하고 리턴
- 옵셔널을 한 단계 평탄화(Optional<Optional<T>> → Optional<T>)
- 중첩된 배열([[T]])을 하나의 배열([T])로 변환
- 중첩된 옵셔널(Optional<Optional<T>>)을 하나의 옵셔널(Optional<T>)로 변환
- 비동기 스트림(Publisher<Publisher<T>>)을 단순한 스트림(Publisher<T>)으로 변환
let nestedArray = [[1,2,3], [1,2,3], [1,2,3]]
var numbers = nestedArray.flatMap { $0 }
print(numbers)
let thirdnestedArray = [[[1,2,3],[4,5,6]], [[1,2,3],[4,5,6]]]
var numbers2 = thirdnestedArray.flatMap { $0 }.flatMap { $0 }
print(numbers2)
- 삼차원 배열의 경우 FlatMap을 한 번 더 사용해서 중첩을 풀 수 있습니다.
728x90
'iOS > Swift 문법' 카테고리의 다른 글
강함참조 사이클(Strong Reference Cycles Between Class Instances) (0) | 2025.03.03 |
---|---|
스위프트 메모리 관리 모델 ARC(Automatic Reference Counting) (0) | 2025.03.03 |
탈출 클로저(Escaping Closures) / 자동 클로저 (Autoclosures) (0) | 2025.02.28 |
중첩함수 (클로저의 캡처와 동일한 현상) (0) | 2025.02.26 |
트레일링(Trailing)클로저 - 후행클로저 문법 (0) | 2025.02.25 |