CompactMap for optional unwrapping in Swift - Time & Space Complexity
We want to understand how the time it takes to run code using compactMap changes as the input list grows.
Specifically, how does unwrapping optionals with compactMap affect performance?
Analyze the time complexity of the following code snippet.
let numbers: [Int?] = [1, nil, 3, nil, 5]
let unwrapped = numbers.compactMap { $0 }
print(unwrapped)
This code takes an array of optional integers and creates a new array with only the non-nil values.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The
compactMapmethod loops through each element in the array once. - How many times: It runs the closure once for every element in the input array.
As the array gets bigger, the number of checks grows in direct proportion.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 checks for nil and unwrap attempts |
| 100 | 100 checks for nil and unwrap attempts |
| 1000 | 1000 checks for nil and unwrap attempts |
Pattern observation: The work grows evenly as the input size grows. Double the input, double the work.
Time Complexity: O(n)
This means the time to run grows in a straight line with the number of items in the array.
[X] Wrong: "Using compactMap is slower because it does extra work to unwrap optionals."
[OK] Correct: compactMap only checks each item once, so it runs in linear time just like a simple loop.
Understanding how compactMap works helps you explain efficient ways to handle optional values in arrays, a common task in Swift programming.
"What if we used map instead of compactMap? How would the time complexity change?"
Practice
compactMap function do when used on an array of optionals in Swift?Solution
Step 1: Understand what
compactMapdoescompactMaptakes an array of optionals and unwraps each element, removing anynilvalues.Step 2: Compare with other options
It does not convert types, sort, or replacenilwith zero. It only filters outniland unwraps values.Final Answer:
It unwraps optionals and removes all nil values from the array. -> Option AQuick Check:
compactMap removes nil = B [OK]
- Confusing compactMap with map (which keeps nils)
- Thinking compactMap sorts or changes types
- Assuming compactMap replaces nil with default values
compactMap on an array numbers of type [Int?] to get an array of non-optional Int values?Solution
Step 1: Understand the input and output types
numbersis an array of optional integers[Int?]. We want to unwrap and removenilvalues to get[Int].Step 2: Check each option's correctness
let result = numbers.compactMap { $0 } usescompactMap { $0 }which unwraps optionals and removesnil. let result = numbers.compactMap { Int($0) } tries to convert optional Int to Int again, which is unnecessary. let result = numbers.compactMap { $0! } force unwraps, which can crash ifnil. let result = numbers.compactMap { String($0) } converts to String, changing type.Final Answer:
let result = numbers.compactMap { $0 } -> Option AQuick Check:
Use compactMap with identity closure to unwrap optionals [OK]
- Using force unwrap inside compactMap causing runtime errors
- Trying to convert optionals unnecessarily
- Changing the type unintentionally
let values: [Int?] = [1, nil, 3, nil, 5]
let unwrapped = values.compactMap { $0 }
print(unwrapped)Solution
Step 1: Understand the input array
The arrayvaluescontains optional integers with somenilvalues.Step 2: Apply
compactMapcompactMap { $0 }unwraps optionals and removesnilvalues, resulting in[1, 3, 5].Final Answer:
[1, 3, 5] -> Option BQuick Check:
compactMap removes nils and unwraps = [1, 3, 5] [OK]
- Expecting optionals in output instead of unwrapped values
- Thinking nils remain in the output
- Confusing compactMap with map
let strings: [String?] = ["apple", nil, "banana"]
let lengths = strings.compactMap { $0.count }
print(lengths)Solution
Step 1: Analyze the closure inside compactMap
The closure uses$0.count, but$0is an optionalString?. Accessingcountdirectly on optional causes error.Step 2: Correct the closure to safely unwrap
Using$0?.countreturns an optional Int, which compactMap unwraps and removes nils, fixing the error.Final Answer:
Error: Cannot use $0.count on optional; fix by using compactMap { $0?.count } -> Option DQuick Check:
Use optional chaining inside compactMap closure [OK]
- Trying to access property directly on optional causing error
- Using map instead of compactMap losing nil filtering
- Force unwrapping causing runtime crashes
[String: Int?] representing item stock counts, how can you create a new dictionary with only items that have a non-nil stock count using compactMap or similar methods?Solution
Step 1: Understand dictionary optional values
The dictionary has optional Int values. We want to remove keys with nil values and unwrap the rest.Step 2: Use
compactMapValuesto unwrap and filtercompactMapValues { $0 }unwraps optionals in values and removes entries with nil values, producing a dictionary with non-optional Int values.Final Answer:
Use compactMapValues { $0 } to unwrap and filter out nil values. -> Option CQuick Check:
compactMapValues unwraps and filters dictionary values [OK]
- Using mapValues with force unwrap risking crashes
- Filtering without unwrapping values
- Trying to use compactMap directly on dictionary
Ready to prove it?
Pass the test and this pattern moves unknown
