What are the higher-order functions in Swift? How to use functional programming features like map, filter, and reduce?
Swift provides a rich set of higher-order functions that support functional programming paradigms. These functions can accept other functions as parameters or return functions, making code more concise and declarative.
Main Higher-Order Functions:
-
map:
- Applies a transformation function to each element in a collection
- Returns a new array containing the transformed elements
- Keeps the original collection unchanged
- Example:
swift
let numbers = [1, 2, 3, 4, 5] let doubled = numbers.map { $0 * 2 } // [2, 4, 6, 8, 10] let names = ["alice", "bob", "charlie"] let capitalized = names.map { $0.capitalized } // ["Alice", "Bob", "Charlie"]
-
filter:
- Filters elements in a collection based on a condition
- Returns a new array containing elements that satisfy the condition
- Example:
swift
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let evenNumbers = numbers.filter { $0 % 2 == 0 } // [2, 4, 6, 8, 10] let words = ["apple", "banana", "pear", "grape"] let longWords = words.filter { $0.count > 4 } // ["apple", "banana"]
-
reduce:
- Combines elements in a collection into a single value
- Accepts an initial value and a combining function
- Example:
swift
let numbers = [1, 2, 3, 4, 5] let sum = numbers.reduce(0) { $0 + $1 } // 15 let product = numbers.reduce(1) { $0 * $1 } // 120 let names = ["Alice", "Bob", "Charlie"] let allNames = names.reduce("") { $0 + $1 + " " } // "Alice Bob Charlie "
-
flatMap:
- Applies a transformation function to each element and flattens the result
- Handles nested arrays or optional values
- Example:
swift
let numbers = [[1, 2], [3, 4], [5, 6]] let flattened = numbers.flatMap { $0 } // [1, 2, 3, 4, 5, 6] let optionalNumbers: [Int?] = [1, nil, 3, nil, 5] let nonNilNumbers = optionalNumbers.flatMap { $0 } // [1, 3, 5]
-
compactMap:
- Similar to map, but filters out nil values
- Specifically designed for handling optional values
- Example:
swift
let strings = ["1", "2", "three", "4", "five"] let numbers = strings.compactMap { Int($0) } // [1, 2, 4]
-
forEach:
- Performs an operation on each element in a collection
- Does not return a new value
- Example:
swift
let numbers = [1, 2, 3, 4, 5] numbers.forEach { print($0) }
-
sorted:
- Sorts a collection
- Can customize sorting rules
- Example:
swift
let numbers = [5, 2, 8, 1, 9] let ascending = numbers.sorted { $0 < $1 } // [1, 2, 5, 8, 9] let descending = numbers.sorted { $0 > $1 } // [9, 8, 5, 2, 1]
Method Chaining:
swiftlet numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let result = numbers .filter { $0 % 2 == 0 } .map { $0 * $0 } .reduce(0) { $0 + $1 } // 220 (2² + 4² + 6² + 8² + 10²)
Best Practices:
- Prioritize using higher-order functions over for loops
- Reasonably use method chaining to improve code readability
- Be aware of performance impact, avoid excessive nesting
- Use meaningful variable names to improve code clarity
- Use traditional loops for complex logic to improve maintainability