Lesson 48Closures
Filter & Reduce
Filter & Reduce
Two powerful higher-order functions that work perfectly with closures. filter selects elements, reduce combines them!
Filter vs Reduce
filter
Returns array of matching elements
.filter { $0 > 5 }reduce
Returns single combined value
.reduce(0, +)Filter Syntax
array.filter { element in
// return true to keep
}
// return true to keep
}
Reduce Syntax
array.reduce(initialValue) { accumulator, element in
// return new accumulated value
}
// return new accumulated value
}
Reduce Variants
reduceCreates new value each iteration
reduce(into:)Mutates result in place (faster)
Power of Chaining
Combine filter, map, and reduce for powerful data transformations!
numbers.filter { }.map { }.reduce(0, +)main.swift
// FILTER - Keep elements that match a condition
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// Keep only even numbers
let evens = numbers.filter { $0 % 2 == 0 }
print(evens) // [2, 4, 6, 8, 10]
// Keep numbers greater than 5
let big = numbers.filter { $0 > 5 }
print(big) // [6, 7, 8, 9, 10]
// Multiple conditions
let special = numbers.filter { $0 > 3 && $0 < 8 }
print(special) // [4, 5, 6, 7]
// FILTER WITH STRINGS
let words = ["apple", "banana", "cherry", "date", "elderberry"]
let longWords = words.filter { $0.count > 5 }
print(longWords) // ["banana", "cherry", "elderberry"]
let startsWithB = words.filter { $0.hasPrefix("b") }
print(startsWithB) // ["banana"]
// FILTER WITH OBJECTS
struct Product {
let name: String
let price: Double
let inStock: Bool
}
let products = [
Product(name: "iPhone", price: 999, inStock: true),
Product(name: "MacBook", price: 1999, inStock: false),
Product(name: "AirPods", price: 199, inStock: true)
]
let available = products.filter { $0.inStock }
let affordable = products.filter { $0.price < 500 }
// REDUCE - Combine all elements into one value
// reduce(initialValue) { accumulator, element in ... }
// Sum all numbers
let sum = numbers.reduce(0) { $0 + $1 }
print(sum) // 55
// Or even shorter!
let sum2 = numbers.reduce(0, +)
print(sum2) // 55
// Product of all numbers
let product = numbers.reduce(1, *)
print(product) // 3628800
// Find maximum
let max = numbers.reduce(numbers[0]) { $0 > $1 ? $0 : $1 }
print(max) // 10
// REDUCE WITH STRINGS
let letters = ["S", "w", "i", "f", "t"]
let word = letters.reduce("") { $0 + $1 }
print(word) // "Swift"
// Join with separator
let joined = letters.reduce("") {
$0.isEmpty ? $1 : $0 + "-" + $1
}
print(joined) // "S-w-i-f-t"
// REDUCE INTO - More efficient for collections
// Avoids creating new instances each iteration
let sentence = "hello world hello swift world"
let wordFrequency = sentence.split(separator: " ").reduce(into: [:]) { counts, word in
counts[String(word), default: 0] += 1
}
print(wordFrequency) // ["hello": 2, "world": 2, "swift": 1]
// Group items
let grouped = numbers.reduce(into: [String: [Int]]()) { result, num in
let key = num % 2 == 0 ? "even" : "odd"
result[key, default: []].append(num)
}
print(grouped) // ["even": [2,4,6,8,10], "odd": [1,3,5,7,9]]
// CHAINING FILTER + MAP + REDUCE
let scores = [85, 92, 78, 95, 88, 72, 90]
let result = scores
.filter { $0 >= 80 } // Keep passing scores
.map { Double($0) } // Convert to Double
.reduce(0, +) // Sum them
let average = result / Double(scores.filter { $0 >= 80 }.count)
print("Average of passing: \(average)")
// PRACTICAL: Shopping cart total
struct CartItem {
let name: String
let price: Double
let quantity: Int
}
let cart = [
CartItem(name: "Apple", price: 1.50, quantity: 4),
CartItem(name: "Bread", price: 2.50, quantity: 2),
CartItem(name: "Milk", price: 3.00, quantity: 1)
]
let total = cart.reduce(0.0) { $0 + ($1.price * Double($1.quantity)) }
print("Cart total: $\(total)") // $14.00Try It Yourself!
Given [1,2,3,4,5,6,7,8,9,10], use filter and reduce to find the sum of all odd numbers!