검색결과 리스트
reduce에 해당되는 글 1건
- 2015.06.22 [swift] Map, Filter, Reduce
글
[swift] Map, Filter, Reduce
함수를 인자로 취하는 함수를 고차원 함수(higher-order function)라고 합니다.
Swift 표준라이브러리에서 array의 메서드로 제공하는 고차원 함수인 map, filter, reduce에 대해서 알아보겠습니다.
1. Map
func map<U>(transform: (T) -> U) -> Array<U>
Map은 배열 각 요소 x에 변환함수 transform을 적용하고 그 결과값으로 구성된 배열을 반환하는 함수입니다.
배열요소들을 다른 값으로 맵핑하는 함수이지요.
2. Filter
func filter(includeElement: (T) -> Bool) -> Array<T>
Filter는 조건식을 인자로 받아, 조건식이 true를 만족하는 요소들로만 구성된 배열을 반환하는 함수입니다.
쉽게 말하면, 배열요소들을 필터링하는 함수입니다.
3. Reduce
func reduce<U>(initial: U, combine: @noescape (U, T) -> U) -> U
Reduce는 U를 초기값으로 하여,각 배열요소들과 순차적으로 결합연산을 하여 누적된 단일값을 반환하는 함수입니다.
4. 사용예
이제 사용법에 대해서 알아볼까요? 다음과 같은 정수형 배열이 있습니다.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- 1. 정수형 배열의 각 요소에 1을 더한 배열을 얻고 싶다.
- 2. 정수형 배열의 각 요소에 2를 곱한 배열을 얻고 싶다.
- 3. 정수형 배열에서 짝수로만 구성된 배열을 얻고 싶다.
- 4. 정수형 배열 값들의 총합을 얻고 싶다.
map 함수를 사용하여 1,2번 문제의 답을 쉽게 얻을 수 있습니다.
// 1. 정수형 배열의 각 요소에 2를 곱한 배열을 얻고 싶다.
arr.map { (x) -> Int in
return x+1
}
// 2. 정수형 배열의 각 요소에 2를 곱한 배열을 얻고 싶다.
arr.map { (x) -> Int in
return x*2
}
filter를 사용하여 3번을 해결해보겠습니다.
// 3. 정수형 배열에서 짝수로만 구성된 배열을 얻고 싶다.
arr.filter { (x) -> Bool in
return x%2 == 0
}
당연히 4번은 reduce의 몫입니다.
// 4. 정수형 배열 값들의 총합을 얻고 싶다.
arr.reduce(0, combine: { (result, x) -> Int in
return result + x
})
Trailing Closure 를 사용하여 다소 낯선 형태지만 코드가 너무 짧아 놀라셨죠?
(Trailing Closure는 함수의 마지막 인자가 클로져(함수)일 경우, 클로져를 함수 호출부의 꼬리(trailing)에 표기하는 방식입니다. )
이러한 고차원 함수들을 복합적으로 사용하여 프로그래밍하는 방식을 함수형 프로그래밍이라고 합니다.
함수형 프로그래밍은 짧고 명료한 코드를 작성할 수 있게하고, 버그의 가능성 또한 훨씬 줄인다고 합니다.
낯선 함수형 프로그래밍 방식에 익숙해지려면 다소 시간이 걸리겠지요? ^^
5. Map 함수 구현하기
학습한 내용을 좀더 잘 이해하기 위해 직접 map 함수를 만들어 보겠습니다.
일반적인 방법으로 1,2번 문제를 구현하는 코드를 작성했습니다.
var arr = [1, 2, 3, 4, 5]
func pluseOne(arr:[Int]) -> [Int] {
var result:[Int] = []
for x in arr {
result.append(x + 1)
}
return result
}
func multiplyTwo(arr:[Int]) -> [Int] {
var result:[Int] = []
for x in arr {
result.append(x * 2)
}
return result
}
두 함수는 연산하는 행위만 제외하고 거의 비슷합니다. 연산하는 행위를 함수로 묶어내면 일반화가 가능해보이네요.
func map(arr:[Int], transform:(Int->Int)) -> [Int] {
var result:[Int] = []
for x in arr {
result.append(transform(x))
}
return result
}
이제 제네릭을 사용하여 범용타입으로 대치하면
func map<T, U>(arr:[T], transform:(T->U)) -> [U] {
var result:[U] = []
for x in arr {
result.append(transform(x))
}
return result
}
map 함수가 완성되었습니다. 우리는 글로벌 함수로 구현했지만 표준라이브러리에서는 array의 메소드로 제공한다는 점이 유일한 차이입니다.
5. Filter 함수 구현하기
Map 함수를 구현해보아서 Filter 함수 구현은 좀더 간단합니다.
// 일반적인 방법으로 구현하고
func filter(arr:[Int]) -> [Int] {
var result:[Int] = []
for x in arr {
if x%2 == 0 {
result.append(x)
}
}
return result
}
// 함수로 공통 행위를 묶어낸 다음
func filter(arr:[Int], includeElement:(Int->Bool)) -> [Int] {
var result:[Int] = []
for x in arr {
if includeElement(x) {
result.append(x)
}
}
return result
}
// 제네릭 적용
func filter<T>(arr:[T], includeElement:(T->Bool)) -> [T] {
var result:[T] = []
for x in arr {
if includeElement(x) {
result.append(x)
}
}
return result
}
6. Reduce 함수 구현하기
단계적으로 구현해보니 고차원 함수 구현이 어렵지 않죠? 이제 reduce를 구현해 볼까요?
// 일반적으로 구현하고
func reduce(arr:[Int]) -> Int {
var result:Int = 0
for x in arr {
result = result + x
}
return result
}
// 초기값 할당과 누적하는 행위를 파라미터로 분리하고
func reduce(arr:[Int], initial:Int, combine:(Int,Int)->Int) -> Int {
var result:Int = initial
for x in arr {
result = combine(result, x)
}
return result
}
// 제네릭 적용
func reduce<T, U>(arr:[T], initial:U, combine:(U, T)->U) -> U {
var result:U = initial
for x in arr {
result = combine(result, x)
}
return result
}
지금까지 Swift 표준라이브러리의 Map, Filter, Reduce에 대해 알아보았습니다.
'Swift' 카테고리의 다른 글
| [swift2] Xcode7 beta2 Swift 언어 변경사항 (0) | 2015.06.24 |
|---|---|
| [swift] 문자열 Indexing과 Slicing (0) | 2015.06.23 |
| [swift] Map, Filter, Reduce (0) | 2015.06.22 |
| [swift2] New in Swift2.0 (0) | 2015.06.19 |
| [swift] Apple Swift Blog (0) | 2015.06.10 |
| [swift] Swift 기초 - 4 (0) | 2014.10.29 |