티스토리 뷰
고차함수 ?
매개변수로 함수를 갖는 함수를 말한다.
Swift 표준 라이브러리에서는 다음과 같은 고차함수를 제공한다.
- map
- filter
- reduce
모두 컨테이너 타입(Array, Set, Dictionary 등)과 Optional 타입에서 사용할 수 있다.
왜 ?
함수형 프로그래밍의 장점을 간편하게 이용할 수 있기 때문이다.
- for-in 구문에 비해 코드가 간결해진다.
- 코드 재사용, 컴파일러 최적화 측면에서 성능 차이가 있다.
- 멀티스레드 환경에서 부작용을 방지한다.
map - 변형
map 함수는 컨테이너 내부의 기존 데이터를 변형하여 새로운 컨테이너를 생성한다.
for-in 구문과 비슷한 동작원리이지만 map를 사용하게되면 클로저 상수를 통해 코드의 재사용이 용이해지고 컴파일러 최적화 측면에서 성능이 좋아진다.
- Array, Dictionary, Set, Optional 등에 사용 가능
- Sequence, Collection 프로토콜을 따르는 타입에 사용 가능
선언
func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]
예제
let numbers = [1, 2, 3, 4, 5]
var forInNumbers: [Int] = []
for number in numbers {
forInNumbers.append(number * 2)
}
// [2, 4, 6, 8, 10]
map을 사용하지 않고 for-in구문을 사용하여 numbers의 요소를 2배로 바꿔보았다.
2배로 곱하여 요소들을 담아야 할 새로운 배열을 만들어서 사용해야한다.
let mapNumbers = numbers.map { number in
return number * 2
}
// [2, 4, 6, 8, 10]
map을 사용하여 같은 동작을 한다면 코드가 더 깔끔해진 것을 확인할 수 있다.
초기에 빈 배열을 만들 필요가 없고, append() 를 수행하지 않아 시간이 절약된다.
let mapNumbers = numbers.map { $0 * 2 }
// [2, 4, 6, 8, 10]
위와 같이 추론을 이용하여 코드 작성이 가능하다.
filter - 추출
컨테이너 값을 특정 조건에 맞게 걸러내는 고차함수이다.
컨테이너 내부의 값을 걸러서 새로운 컨테이너로 추출한다.
filter의 매개변수르 전달되는 함수의 반환 타입은 Bool이다.
true면 값을 포함하고 false면 값을 배제한다.
선언
func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> [Self.Element]
예제
numbers.filter { number in
return number % 2 == 0
}
let filterNumbers = numbers.filter { $0 % 2 == 0 }
// [2, 4]
위와 같이 numbers 배열에서 짝수만 추출하여 새로운 컨테이너로 만든다.
let filterMapNumbers = numbers
.filter { $0 % 2 == 0 }
.map { $0 * 2 }
// [4, 8]
map과 함께 사용할 수 있다.
reduce - 통합
컨테이너 내의 모든 값을 하나로 통합하는 고차함수이다.
상황에 따라 reduce를 map과 비슷하게 사용할 수 있다.
선언 1
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
클로저가 각 요소를 전달받아 연산한 후, 값을 다음 클로저 실행을 위해 반환하며 컨테이너를 순환하는 형태이다.
- initialResult : 초기값
- nextPartialResult : 클로저로 두 개의 매개변수를 받는다.
- Result : initialResult로 받은 초기값 혹은 이전 클로저의 결과값, reduce의 순회가 끝났을 때 최종 결과값이다.
- Element : reduce 메소드가 순환하는 컨테이너의 요소
예제
let reduceNumbers = numbers.reduce(0) { partialResult, element in
return partialResult + element
}
// 15
let reduceNumbers2 = numbers.reduce(0) { $0 + $1 }
// 15
let reduceNumbers3 = numbers.reduce(0, +)
// 15
초기값 0을 가지고 numbers의 모든 값을 더한다.
모두 같은 값을 출력하는 것을 확인하고 축약이 가능하다는 것을 확인했다.
선언 2
func reduce<Result>(into initialResult: Result, _ updateAccumulatingResult: (inout Result, Self.Element) throws -> ()) rethrows -> Result
컨테이너를 순환하며 클로저가 실행되지만 클로저가 따로 결과값을 반환하지 않는 상태
return 없이 inout 매개변수를 사용해 초기값에 직접 연산을 실행한다.
- initialResult : 초기값
- updateAccumulatingResult : 클로저로 두 개의 매개변수를 갖는다.
- inout Result : initialResult로 전달받은 초기값 또는 이전 클로저에 의해 변경된 결과값, reduce의 순회가 끝났을 때 최종 결과값이다.
- Element : reduce 메소드가 순환하는 컨테이너 요소
예제
let reduceIntoNumbers = numbers.reduce(into: 0) { partialResult, number in
partialResult += number
}
초기값 0에 numbers의 모든 값을 더한다.
클로저 값의 return없이 클로저 내부에서 직접 이전 값을 변경한다.
let names = ["harry", "lily"]
let uppercaseNames = names.reduce(into: [], {
$0.append($1.uppercased())
})
// ["HARRY", "LILY"]
// map
names.map { $0.uppercased() } // ["HARRY", "LILY"]
map, filter 와 유사하게 사용 가능하다.
다 섞어서 사용해보기 (map, filter, reduce)
let result = numbers
.filter { $0 % 2 == 0 } // 짝수 걸러내기
.map { $0 * 5 } // 5 곱하기
.reduce(0, +) // 모든 값 더하기
// 50
'iOS > Swift' 카테고리의 다른 글
[Swift] Frame, Bounds (0) | 2023.01.17 |
---|---|
[Swift] 고차함수 (2) - flatMap, compactMap (0) | 2022.12.28 |
[Swift] Protocol (2) (0) | 2022.12.16 |
[Swift] Protocol (1) (0) | 2022.12.14 |
[Swift] 열거형 (Enumerations) (1) | 2022.12.07 |
- Total
- Today
- Yesterday
- 의미있는이름
- CodingTest
- frame과 bounds 차이
- AWS Fargate
- tabview
- IOS
- Custom
- onTapGesture
- ChatGPT
- AWS
- Swift
- file private
- navigation
- 카메라
- Git
- Generic
- 곰튀김
- strcut
- enumerations
- ObservedObject
- rxswift
- docker
- Xcode
- MVVM
- Protocol
- kakao
- OCR
- delegate
- Login
- SwiftUI
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |