Working with Collections
Prerequisites: map, filter, and reduce, Structs
Real programs spend much of their time sorting, grouping, and searching collections of structs. Swift's collection methods make this concise.
struct Order {
let customer: String
let total: Double
let isPaid: Bool
}
let orders = [
Order(customer: "Ada", total: 120, isPaid: true),
Order(customer: "Linus", total: 45, isPaid: false),
Order(customer: "Ada", total: 80, isPaid: true),
Order(customer: "Grace", total: 300, isPaid: true),
]
Sorting by a property
let byTotal = orders.sorted { $0.total > $1.total }
print(byTotal.map(\.customer))
["Grace", "Ada", "Ada", "Linus"]
Searching
print(orders.first(where: { !$0.isPaid })?.customer ?? "none")
print(orders.contains { $0.total > 250 })
print(orders.firstIndex(where: { $0.customer == "Grace" }) ?? -1)
print(orders.filter(\.isPaid).count)
Linus
true
3
3
Grouping and totaling
Dictionary(grouping:by:) groups elements by a key:
let byCustomer = Dictionary(grouping: orders, by: \.customer)
for customer in byCustomer.keys.sorted() {
let spent = byCustomer[customer, default: []].map(\.total).reduce(0, +)
print("\(customer): \(spent)")
}
Ada: 200.0
Grace: 300.0
Linus: 45.0
Combining sequences
let names = ["Ada", "Linus", "Grace"]
let scores = [92, 78, 88]
for (name, score) in zip(names, scores) {
print("\(name): \(score)")
}
let lookup = Dictionary(uniqueKeysWithValues: zip(names, scores))
print(lookup["Grace"] ?? 0)
Ada: 92
Linus: 78
Grace: 88
88
zip pairs up two sequences element by element.
Slices
prefix, suffix, dropFirst, and ranges like orders[1...2] return
an ArraySlice — a lightweight view into the original array. Wrap it in
Array(...) if you want to keep it around independently.
Practice
Using the orders array, print the names of customers with unpaid
orders, and the average total of paid orders.
Show solution
let unpaid = orders.filter { !$0.isPaid }.map(\.customer)
print(unpaid)
let paid = orders.filter(\.isPaid)
let average = paid.map(\.total).reduce(0, +) / Double(paid.count)
print(average)
["Linus"]
166.66666666666666