Chapter 67: Swift map, filter, reduce
1. The Big Picture – Why do we need map, filter, reduce?
These three functions are the core tools for working with collections in a functional, declarative style.
They allow you to:
- transform every element → map
- select only some elements → filter
- combine all elements into one value → reduce
Together they replace most of the old-style loops with for and var result = ….
Golden rule used by almost every modern Swift developer:
Whenever you want to create a new collection from an existing one → prefer map / filter / compactMap / flatMap over manual for loops
2. map – transform every element
map creates a new array by applying the same transformation to every element of the original collection.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
let numbers = [1, 2, 3, 4, 5] // Classic for loop way var doubled: [Int] = [] for n in numbers { doubled.append(n * 2) } // Modern map way (preferred) let doubled = numbers.map { $0 * 2 } // or more explicit: let doubled2 = numbers.map { number in number * 2 } |
Realistic examples
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
let names = ["Rahul", "Priya", "Aarav", "Sneha"] // Capitalize every name let capitalized = names.map { $0.uppercased() } // ["RAHUL", "PRIYA", "AARAV", "SNEHA"] // Add "Mr./Ms." prefix let formalNames = names.map { name in name.hasPrefix("A") || name.hasPrefix("E") ? "Mr. \(name)" : "Ms. \(name)" } // Convert to view models struct UserViewModel { let displayName: String let initial: String } let viewModels = names.map { name in UserViewModel( displayName: name, initial: String(name.prefix(1)) ) } |
Common real-life use-cases for map:
- Convert data models to view models
- Format numbers/dates for display
- Transform API response into domain models
- Prepare data for UI (add prefixes, icons, colors…)
3. filter – select only some elements
filter creates a new array containing only the elements that satisfy a condition.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
let scores = [78, 92, 65, 88, 45, 95, 72] // Classic way var passing: [Int] = [] for score in scores { if score >= 75 { passing.append(score) } } // Modern filter way let passing = scores.filter { $0 >= 75 } // [78, 92, 88, 95, 72] |
Realistic examples
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
let products = [ "iPhone 16 Pro", "AirPods Pro", "Phone Case", "MacBook Air", "Screen Protector" ] // Only expensive products let premium = products.filter { $0.contains("Pro") || $0.contains("MacBook") } // ["iPhone 16 Pro", "AirPods Pro", "MacBook Air"] // Active users only let users = [ (name: "Rahul", isActive: true), (name: "Priya", isActive: false), (name: "Aarav", isActive: true), (name: "Sneha", isActive: true) ] let activeUsers = users.filter { $0.isActive }.map { $0.name } // ["Rahul", "Aarav", "Sneha"] |
Common real-life use-cases for filter:
- Show only active users / visible items
- Filter products by price/category/availability
- Keep only valid form fields / search results
- Remove nil / invalid entries (combine with compactMap)
4. reduce – combine all elements into one value
reduce takes all elements and accumulates them into a single result.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
let numbers = [1, 2, 3, 4, 5] // Classic way var sum = 0 for n in numbers { sum += n } // reduce way let sum = numbers.reduce(0, +) // 15 // or more explicit: let sum2 = numbers.reduce(0) { $0 + $1 } // same |
Realistic examples
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Total price in cart let prices = [3499.00, 799.00, 499.00] let total = prices.reduce(0.0, +) // 4797.0 // Concatenate strings let words = ["Hello", "from", "Hyderabad"] let sentence = words.reduce("") { $0 + " " + $1 }.trimmingCharacters(in: .whitespaces) // "Hello from Hyderabad" // Count words longer than 5 letters let longWordsCount = words.reduce(0) { count, word in word.count > 5 ? count + 1 : count } |
Common real-life use-cases for reduce:
- Calculate sum, average, max, min
- Build a string (CSV line, concatenated names)
- Accumulate stats (total price, word count, score sum)
- Combine objects (merge dictionaries, combine permissions)
5. Very Common Real-Life Combined Example (map + filter + reduce)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
struct Order { let item: String let price: Double let isPremium: Bool } let orders = [ Order(item: "Earbuds", price: 3499, isPremium: true), Order(item: "Case", price: 799, isPremium: false), Order(item: "Charger", price: 999, isPremium: true), Order(item: "Protector", price: 499, isPremium: false) ] // Real one-liner pattern used in many apps let premiumTotal = orders .filter { $0.isPremium } // only premium items .map { $0.price } // extract prices .reduce(0.0, +) // sum them print("Total from premium items: ₹\(String(format: "%.2f", premiumTotal))") // Total from premium items: ₹4498.00 |
Alternative readable style (often preferred in teams):
|
0 1 2 3 4 5 6 7 8 |
let premiumOrders = orders.filter { $0.isPremium } let premiumPrices = premiumOrders.map { $0.price } let totalPremium = premiumPrices.reduce(0.0, +) |
6. Very Common Beginner Mistakes & Correct Habits
| Mistake | Wrong / Dangerous code | Correct / Better habit | Why? |
|---|---|---|---|
| Mutating original array inside map/filter | numbers.map { numbers.append($0 * 2) } | Never mutate original inside transformation | Runtime error or unexpected behavior |
| Force-unwrapping inside map | array.map { $0! } | Use compactMap for optionals | Crash if any nil |
| Using reduce for simple sum | reduce(0) { $0 + $1 } | reduce(0, +) | Shorter & clearer |
| Confusing map and forEach | array.map { print($0) } | Use forEach for side-effects | map should return transformed values |
| Forgetting map/filter create new arrays | array.map { $0 * 2 } then expect original changed | Understand map/filter/reduce return new values | Original array stays unchanged |
7. Quick Reference – Most Used Patterns
| Goal | Most idiomatic code | Notes / Tip |
|---|---|---|
| Transform every element | array.map { … } | Returns new array |
| Keep only some elements | array.filter { $0 > 10 } | Returns new array |
| Convert optionals & remove nil | array.compactMap { $0 } | Removes nil, unwraps |
| Flatten nested arrays | array.flatMap { $0 } | Turns [[1,2],[3,4]] → [1,2,3,4] |
| Sum / average / max | array.reduce(0, +) or array.reduce(0.0) { $0 + $1 } | reduce(into:) variant also very popular |
| Build string from elements | array.map(String.init).joined(separator: “, “) | Very frequent for CSV, logs |
8. Small Practice – Try these
- Create array of 6 numbers → Use map to multiply each by 3 → Use filter to keep only numbers > 15 → Use reduce to calculate their sum
- Create array of 5 names → Use map to capitalize each name → Use filter to keep only names longer than 5 letters → Use joined to make one comma-separated string
- Create array of optional Ints [Int?] = [1, nil, 3, nil, 5] → Use compactMap to get [1,3,5] → Sum them with reduce
Paste your code here if you want feedback or want to see more elegant versions!
What would you like to explore next?
- compactMap, flatMap, reduce(into:) in depth
- Combining map + filter + reduce chains
- forEach vs for-in vs map decision guide
- Collections in SwiftUI (List, ForEach, @State)
- Or move to another topic (dictionaries, sets, optionals, switch…)
Just tell me — we’ll continue in the same clear, patient, detailed style 😊
