[Swift] 고차함수(2) - map, flatMap, compactMap

728x90

 

고차함수(Higher-order-function)중 map, flatMap, compactMap에 대해 알아 보겠습니다.

 

map

map은 배열 내부의 값을 하나씩 mapping한다고 생각하면 쉽게 다가올껍니다.
각 요소에 대한 값을 변경하고자 할때 사용하고, 그 결과들을 배열의 상태로 반환합니다.

 

Declaration

func map<T>(_ transform: (String) throws -> T) rethrows -> [T]

 

Example

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
names.map {
  $0 + "'s name"
}

<출력>
// ["Chris's name", "Alex's name", "Ewa's name", "Barry's name", "Daniella's name"]


let array = [1,2,3,4,5]
array.map {
    $0 + 1
}

<출력>
// [2, 3, 4, 5, 6]

 


 

flatMap, compactMap

Swift 4.1부터는 flatMap이 compactMap로 변경되지만, flatMap이 없어지는 것이 아닙니다.

 

Declaration

  • flatMap
func flatMap<SegmentOfResult>(_ transform: ([Int]) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence

 

  • compactMap
func compactMap<ElementOfResult>(_ transform: (Int?) throws -> ElementOfResult?) rethrows -> [ElementOfResult]

 

쓰임이 정확히 구별된것입니다!
무슨소리냐!!

 

예제를 확인해보겠습니다.

 

 

Example

let array1 = [1, nil, 3, nil, 5, 6, 7]
let flatMapTest1 = array1.flatMap{ $0 }
let compactMapTest1 = array1.compactMap { $0 }

print("flatMapTest1 :", flatMapTest1)
print("compactMapTest1 :", compactMapTest1)

<출력>
flatMapTest1 : [1, 3, 5, 6, 7]
compactMapTest1 : [1, 3, 5, 6, 7]

 

둘다 동일한 결과를 나타냅니다. 단, 일차원 배열에서만!

 

기존의 flatMap의 경우에는 배열을 1.flatten하게 만들어주며 2.nil을 제거, 3. 옵셔널 바인딩해주는 역할이였습니다. 위의 소스를 작성해보시면 이런 경고창이 뜨실겁니다.

‘flatMap’ is deprecated: Please use compactMap(:) for the case where closure returns an optional value
Use 'compactMap(:)’ instead

 

즉, Swift 4.1부터는 1차원 배열에서 nil을 제거하고 옵셔널 바인딩을 하고싶으실때는 compactMap을 사용하시면 됩니다.

 

2차원 배열의 경우를 살펴 볼까요?

let array2: [[Int?]] = [[1, 2, 3], [nil, 5], [6, nil], [nil, nil]]
let flatMapTest2 = array2.flatMap { $0 }
let compactMapTest2 = array2.compactMap { $0 }

print("flatMapTest2 :",flatMapTest2)
print("compactMapTest2 :",compactMapTest2)

<출력>
// flatMapTest2 : [Optional(1), Optional(2), Optional(3), nil, Optional(5), Optional(6), nil, nil, nil]
// compactMapTest2 : [[Optional(1), Optional(2), Optional(3)], [nil, Optional(5)], [Optional(6), nil], [nil, nil]]

 

flatMapt과 compactMap은 nil을 제거하지않고 1차원 배열일때만 nil제거합니다.
flatMap은 2차원배열을 1차원배열로 flatten 하게 만들어주는 반면, compactMap은 1차원 배열로 만들지 않습니다.

 

즉, 2차원 배열을 1차원으로 flatten하게 만드실때 flatMap을 사용하시면 됩니다!

 

위의 flatMapTest2 출력 결과 값이 옵셔널 처리가 되있는데 1차원 배열이니까 compactMap으로 체이닝 연결해주면 원하는 값을 가져올 수 있겠죠?

let array2: [[Int?]] = [[1, 2, 3], [nil, 5], [6, nil], [nil, nil]]
let flatMapTest2 = array2.flatMap { $0 }.compactMap{ $0 }

<출력>
// flatMapTest2 : [1, 2, 3, 5, 6]

 

 

flatMap과compactMap 정리

  • Swift 4.1부터는 1차원 배열에서 nil을 제거하고 옵셔널 바인딩을 하고싶으실때는 compactMap사용.
  • 2차원 배열을 1차원 배열로 flatten하게 만들때 flatMap을 사용.