Swift Guide to Map Filter Reduce
Next time you find yourself looping over a collection check if you could use map, filter or reduce:
- map returns an Array containing results of applying a transform to each item.
- filter returns an Array containing only those items that match an include condition.
- reduce returns a single value calculated by calling a combine closure for each item with an initial value.
map Full:
let squares3 = values.map({
(value: Double) -> Double in
return value * value
})
map Quicker:
let squares4 = values.map {value in value * value}
map Quickest:
let squares5 = values.map { $0 * $0 }
filter:
let even = digits.filter { $0 % 2 == 0 }
reduce Full:
let names = ["alan","brian","charlie"]
let csv = names.reduce("===") {text, name in "\(text),\(name)"}
// "===,alan,brian,charlie"
reduce quick:
let codes = ["abc","def","ghi"]
let text = codes.reduce("", +)
// "abcdefghi"
flatMap:
let results = [[5,2,7], [4,8], [9,1,3]]
let allResults = results.flatMap { $0 }
// [5, 2, 7, 4, 8, 9, 1, 3]
Using FlatMap on an optional:
let input: Int? = Int("8")
let passMark: Int? = input.flatMap { $0 > 5 ? $0 : nil }
// 8
Using CompactMap on a sequence with a closure that returns an optional:
Note that this use of flatMap was renamed to compactMap in Swift 4.1 (Xcode 9.3). It provides a convenient way to strip nil values from an array:
let keys: [String?] = ["Tom", nil, "Peter", nil, "Harry"]
let validNames = keys.compactMap { $0 }
validNames
// ["Tom", "Peter", "Harry"]
let counts = keys.compactMap { $0?.count }
counts
// [3, 5, 5]