Swift Tutorial · Closures, Generics and Errors · Lesson 19 of 30
Swift map, filter, reduce and More
Transform collections with map, filter, reduce, compactMap, sorted, grouping and key paths.
Transforming collections
Higher-order methods replace most loops and return new collections. Key paths (\.total) can be used where a
closure that reads one property is expected.
struct Order {
let id: Int
let customer: String
let total: Double
let paid: Bool
}
let orders = [
Order(id: 1, customer: "Ana", total: 40, paid: true),
Order(id: 2, customer: "Ben", total: 15.5, paid: false),
Order(id: 3, customer: "Ana", total: 22, paid: true),
Order(id: 4, customer: "Caro", total: 99.9, paid: true),
]
print(orders.filter(\.paid).map(\.id))
print(orders.sorted { $0.total > $1.total }.prefix(2).map(\.customer))
print(orders.map(\.total).reduce(0, +))
print(orders.max { $0.total < $1.total }!.id)
print(orders.contains { !$0.paid })
print(orders.allSatisfy { $0.total > 10 })
Output
[1, 3, 4] ["Caro", "Ana"] 177.4 4 true true
Run this on your computer — see “Get Started” for setup.
Grouping and lazy
Dictionary(grouping:by:) groups elements by a key, and .lazy processes elements only as needed.
let words = ["apple", "avocado", "banana", "blueberry", "cherry"]
let byLetter = Dictionary(grouping: words, by: { $0.first! })
for letter in byLetter.keys.sorted() {
print(letter, byLetter[letter]!)
}
var checked = 0
let firstBig = (1...1_000).lazy.map { n -> Int in checked += 1; return n * n }.first { $0 > 50 }
print(firstBig!, "after", checked, "squares")
Output
a ["apple", "avocado"] b ["banana", "blueberry"] c ["cherry"] 64 after 8 squares
Run this on your computer — see “Get Started” for setup.
Test yourself
What does compactMap do?
Sorts the collectionTransforms each element and drops the nil resultsRemoves duplicatesFlattens nested arrays only
Show answer
Answer: Transforms each element and drops the nil results