Swift Collections Beyond Arrays¶
★★★★★ Intermediate
Arrays are the most common collection, but Swift provides Sets and Dictionaries for different access patterns. Choosing the right collection type directly impacts performance and correctness.
Sets - Unordered Unique Elements¶
A Set stores unique elements with no defined order. Lookup, insertion, and deletion are O(1) average.
// Declaration
var numbers: Set<Int> = [1, 2, 3, 4, 5]
// Duplicates silently ignored
var withDupes: Set<Int> = [1, 2, 2, 3, 3, 3]
print(withDupes.count) // 3
// Order is NOT guaranteed
print(numbers) // could be {3, 1, 5, 2, 4} or any permutation
Set Operations¶
let setA: Set<Int> = [1, 2, 3, 4]
let setB: Set<Int> = [3, 4, 5, 6]
setA.union(setB) // {1, 2, 3, 4, 5, 6}
setA.intersection(setB) // {3, 4}
setA.subtracting(setB) // {1, 2}
setA.symmetricDifference(setB) // {1, 2, 5, 6}
setA.isSubset(of: [1, 2, 3, 4, 5]) // true
setA.isDisjoint(with: [7, 8, 9]) // true (no common elements)
Set API¶
var fruits: Set<String> = ["apple", "banana"]
fruits.insert("cherry") // inserts, returns (inserted: true, ...)
fruits.insert("apple") // no-op, returns (inserted: false, ...)
fruits.remove("banana") // removes by VALUE (not index - sets have no indices)
fruits.contains("apple") // true - O(1) lookup
fruits.count // element count
fruits.isEmpty // boolean check
When to Use Sets¶
| Use Case | Array | Set |
|---|---|---|
| Ordered data | Yes | No |
| Index-based access | Yes | No |
| Fast membership test | O(n) | O(1) |
| Guaranteed uniqueness | Manual | Automatic |
| Duplicates allowed | Yes | No |
| Mathematical operations | Manual | Built-in |
Dictionaries - Key-Value Pairs¶
var user: [String: Any] = [
"name": "Dmitry",
"age": 25,
"isPremium": true
]
// Access (returns Optional because key may not exist)
let name = user["name"] // Optional("Dmitry")
let email = user["email"] // nil
// Default value for missing keys
let email = user["email", default: "none"] // "none"
// Modification
user["email"] = "[email protected]" // add
user["age"] = 26 // update
user.removeValue(forKey: "isPremium") // remove
Iterating Dictionaries¶
for (key, value) in user {
print("\(key): \(value)")
}
// Keys and values as separate collections
let keys = Array(user.keys)
let values = Array(user.values)
Higher-Order Functions on Collections¶
All Swift collections support map, filter, reduce, compactMap, flatMap:
map - Transform Each Element¶
let numbers = [1, 2, 3, 4, 5]
let doubled = numbers.map { $0 * 2 } // [2, 4, 6, 8, 10]
let strings = numbers.map { String($0) } // ["1", "2", "3", "4", "5"]
// map returns same-sized collection with potentially different type
let isEven = numbers.map { $0 % 2 == 0 } // [false, true, false, true, false]
filter - Select Elements¶
reduce - Aggregate to Single Value¶
compactMap - Transform + Remove Nils¶
String Interpolation¶
Swift uses \() syntax for embedding values in strings:
let name = "Anna"
let greeting = "Hello, \(name)!" // "Hello, Anna!"
let calc = "2 * 5 = \(2 * 5)" // "2 * 5 = 10"
// Works with any expression
let price = 9.99
let formatted = "Price: $\(price)" // "Price: $9.99"
This is distinct from concatenation and avoids the spacing issues of passing multiple arguments to print().
Gotchas¶
- Set elements must be Hashable. Custom types need to conform to
Hashableto be stored in a Set or used as Dictionary keys. - Dictionary access returns Optional. Always unwrap safely:
if let value = dict["key"]or use default values:dict["key", default: 0]. - Set order is random. Do not rely on the iteration order of a Set - it may change between runs. If order matters, use an Array and manually ensure uniqueness.
mapon Dictionary returns Array of tuples, not a new Dictionary. To create a new dictionary from a transformation, useDictionary(uniqueKeysWithValues: dict.map { ... })ormapValues.
Cross-References¶
- swift fundamentals - basic types, variables, constants
- swift enums and optionals - Optional handling for dictionary access
- swift generics - generic collection types
- swiftui lists and grids - displaying collections in UI