[이미지 출처 : https://www.joshmorony.com/filtering-mapping-and-reducing-arrays-in-ionic-2/]
Swift에는 컬렉션타입을 사용할 때 매우 편리하게 쓸 수 있는 몇 가지의 함수를 제공한다.
루비 개발자라면 익숙한 Map, Filter, Reduce가 그것이다.
이 3가지 함수는 데이터를 주로 처리하는 작업의 양을 획기적으로 줄여주기 때문에 필수적으로 익혀두는 것이 좋다.
Map
맵은 컬렉션타입을 순환하여 특정 값을 결과값으로 리턴해 준다. 예제를 보자.
let number: Array = [1, 2, 3, 4, 5]
number 배열은 총 5개의 값을 가지고 있다. 만일 해당 값에 일괄적으로 * 2를 하고 싶다면
print( number.map( { (value: Int) -> Int in return value * 2 } ) )
// [2, 4, 6, 8, 10]
이런식으로 사용할 수 있다. 맵은 내부 블록에서 코딩된 내용을 "처리한 후의 값"을 리턴해 준다.
print( number.map( { (value: Int) -> String in return "$" + String(value) } ) )
// ["$1", "$2", "$3", "$4", "$5"]
이런식으로 활용도 가능하다.
그럼 Dictionary의 경우에는 어떨까?
let cars: Dictionary = [
"BMW" : 1000,
"Benz" : 2000,
"Lamborghini" : 3000
]
이런 모양의 Dictionary가 있다고 하자. 이럴경우에는 map의 인자가 두개가 된다.
print( cars.map( { (val1: String, val2: Int) -> Int in return val2 * 2 } ) )
// [2000, 4000, 6000]
만일 차의 이름만 뽑고 싶다면
print( cars.map( { (val1: String, val2: Int) -> String in return val1 } ) )
// ["BMW", "Benz", "Lamborghini"]
이런식으로 하면 된다.
print( cars.map( { (val1: String, val2: Int) -> String in return val1 + ":" + String(val2) } ) )
// ["BMW:1000", "Benz:2000", "Lamborghini:3000"]
이렇게 응용도 가능하다.
주로 Map은 기본 데이터를 컬렉션타입으로 저장을 한 후, 특정 뷰에 "가공된" 값을 사용해야할때 요긴하게 쓸 수 있다.
Filter
다음으로 Filter 함수가 있다. 이 함수는 이름을 보면 쉽게 기능을 예상 가능하듯이 컬렉션타입 내의 특정 조건의 값만 리턴해 준다.
print( number.filter( { (value: Int) -> Bool in return (value % 2 == 0) } ) )
// print = [2, 4]
만일 number 배열에서 2로 나눠서 0인 것만 뽑아 내기 위해서는 위와 같이 사용을 하면 된다.
print( cars.filter( { (val1: String, val2: Int) -> Bool in return val1 == "Benz" } ) )
// print = [(key: "Benz", value: 2000)]
만일 벤츠만 리턴시키고 싶다면 Dictionary에서는 이와 같이 사용하면 된다.
Reduce
만일 컬렉션타입 내부의 값을 더해서 총합을 보여줘야할 때 쉬운 방법이 없을까? 그때 바로 Reduce 함수를 사용하면 된다.
print( number.reduce(0, { (s1: Int, s2: Int) -> Int in return s1 + s2 }) )
// print = 15
Reduce함수는 내부의 연산 코드를 기반으로된 값을 리턴해 준다. 위 코드는 number의 값을 모두 더하는 코드이다.
print( number.reduce(10, { (s1: Int, s2: Int) -> Int in return s1 * s2 }) )
// 10 * 1 * 2 * 3 * 4 * 5
// print = 1200
이렇게 사용도 가능하다.
만일 Dictionary의 경우에는 어떻게 해야할까? 여러가지 방법이 있지만 아래와 같은 방법이 편리하다.
let dicValues = cars.map( { (val1: String, val2: Int) -> Int in return val2 } )
print( dicValues.reduce(0, { (s1: Int, s2: Int) -> Int in return s1 + s2 }) )
// print = 6000
위 내용은 먼저 dicValues에 자동차의 가격을 배열로 저장한다. 결과값은 [1000, 2000, 3000]이 될 것이다.
그 다음 reduce를 이용해서 dicValues의 값들을 합한다.
이 3가지의 함수의 장점은 서로 합체(?)가 가능하다는 점이다. 마지막 Dictionary의 합을 구한것처럼 map과 filter와 reduce 값을 조합해서 쓸 수 있다. 다시 Dictionary를 보자.
let cars: Dictionary = [
"BMW" : 1000,
"Benz" : 2000,
"Lamborghini" : 3000
]
만일 여기서 BMW와 Benz 두 차의 가격만 더하고 싶다고 해 보자.
let procCar = cars.filter( { (val1: String, val2: Int) -> Bool in return (val1 == "Benz" || val1 == "BMW") } )
// [(key: "BMW", value: 1000), (key: "Benz", value: 2000)]
먼저 filter를 이용해서 두 차만 뽑아 낸다.
let carPrice = procCar.map( { (val1: String, val2: Int) -> Int in return val2 } )
// [1000, 2000]
그 후 차의 가격만 map을 이용해서 뽑아낸다.
let SumCarPrice = carPrice.reduce(0, { (s1: Int, s2: Int) -> Int in return s1 + s2 } )
// 3000
마지막으로 reduce를 이용해서 차의 가격을 합하면 끝!
참 쉽죠?
'Swift' 카테고리의 다른 글
SwiftUI, WKWebView 구현하기 (7) | 2021.01.03 |
---|---|
확장(extension)을 이용해서 테이블 뷰 리팩토링하기 (0) | 2017.08.25 |
프로토콜 지향 MVVM 디자인 패턴 적용하기 (0) | 2017.08.25 |
Swift에서 애매한 옵셔널의 처리 (0) | 2017.08.25 |