๐ŸŽ iOS/Swift

[Swift] map, flatMap, compactMap ?

Map, flatMap, compactMap

map

  • ๋ฐฐ์—ด ๋‚ด๋ถ€์˜ ๊ฐ’์„ ํ•˜๋‚˜์”ฉ mapping
  • ๊ฐ ์š”์†Œ์— ๋Œ€ํ•œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ณ ์ž ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋“ค์„ ๋ฐฐ์—ด์˜ ์ƒํƒœ๋กœ ๋ฐ˜ํ™˜
func map<T>(_ transform: (String) throws -> T) rethrows -> [T]
import Foundation

let cast = ["Vivien", "Marlon", "Kim", "Karl"]
let lowercaseNames = cast.map { $0.lowercased() }
print(lowercaseNames) // ["vivien", "marlon", "kim", "karl"]

let letterCounts = cast.map{ $0.count }
print(letterCounts) // [6, 6, 3, 4]

 

flatMap

  • ๋ฐฐ์—ด์„ flattenํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์คŒ
  • nil์„ ์ œ๊ฑฐํ•จ
  • ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ
func flatMap<SegementOfResult>(_ transform: ([Int]) throws -> SegementOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult: Sequence
import Foundation

let numbers = [1,2,3,4]

let mapped = numbers.map { Array(repeating: $0, count: $0)}
print(mapped) // [[1], [2,2], [3,3,3], [4,4,4,4]]

// # flatten #
let flatMapped = numbers.flatMap { Array(repeating: $0, count: $0)}
print(flatMapped) // [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

---------------------------------------------------------------------------
// # nil ์ œ๊ฑฐ #
let numbers = [1,2,nil,3,4]

let flatMapped = numbers.flatMap { $0 } 
print(flatMapped) // [1, 2, 3, 4]

flatMap์„ ์ด์šฉํ•ด์„œ optional binding์„ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ,

compactMap์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 

https://sudonull.com/post/14814-Swift-41-why-Apple-renamed-flatMap-to-compactMap

์œ„ ๋งํฌ์—์„œ๋Š” flatmap ์‚ฌ์šฉ ์‹œ map๊ณผ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋ผ๊ณ  ํ•œ๋‹ค.

let possibleNumbers = ["1", "2", "three", "///4///", "5"]

let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
print(mapped) // [Optional(1), Optional(2), nil, nil, Optional(5)]

// # Optional Binding #
let flatMapped: [Int] = possibleNumbers.flatMap { str in Int(str) }
print(flatMapped)  // [1, 2, 5]

-------> ํ•ด๋‹น ์ผ€์ด์Šค(์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ)์—์„œ๋Š” compactMap ์‚ฌ์šฉ ๊ถŒ์žฅ 

 

 

compactMap

  • nil์„ ์ œ๊ฑฐํ•จ
  • ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ
func compactMap<ElementOfResult>(_ transform: (Int?) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
import Foundation

let numbers = [1,2,nil,3,4]

let compactMapped = numbers.compactMap { $0 }
print(compactMapped) // [1, 2, 3, 4]

---------------------------------------------------------------------------

// # Optional Binding #
let possibleNumbers = ["1", "2", "three", "///4///", "5"]

let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
print(mapped) // [Optional(1), Optional(2), nil, nil, Optional(5)]

let compactMapped: [Int] = possibleNumbers.compactMap { str in Int(str) }
print(compactMapped) // [1, 2, 5]

---------------------------------------------------------------------------

 

flatMap vs compactMap

let arr: [[Int?]] = [[1, 2, 3], [nil, 5], [6, nil], [nil, nil]]
let flatMapped = arr.flatMap { $0 }
// [Optional(1), Optional(2), Optional(3), nil, Optional(5), Optional(6), nil, nil, nil]
let flatMappedAndflatMapped = arr.flatMap { $0 }.flatMap { $0 }
// [1, 2, 3, 5, 6]
let flatMappedAndcompactMapped = arr.flatMap { $0 }.compactMap { $0 } // flat ํ›„ optional binding
// [1, 2, 3, 5, 6]

---------------------------------------------------------------------------

let compactMapped = arr.compactMap { $0 }
// [[Optional(1), Optional(2), Optional(3)], [nil, Optional(5)], [Optional(6), nil], [nil, nil]]
let compactMappedAndflatMapped = arr.compactMap { $0 }.flatMap { $0 }
// [Optional(1), Optional(2), Optional(3), nil, Optional(5), Optional(6), nil, nil, nil]
let compactMappedAndcompactMapped = arr.compactMap { $0 }.compactMap { $0 }
// [[Optional(1), Optional(2), Optional(3)], [nil, Optional(5)], [Optional(6), nil], [nil, nil]]