Collections and Algorithms (with version cues)#
Sequence vs Collection, common transforms, and performance considerations.
Version Quick Reference#
- Swift 5.x+: standard library offers CoW collections, lazy views, and SIMD-backed
ContiguousArray. - Swift 5.7+: improved type inference with primary associated types;
any spelling required for existentials. - Swift 5.9+: parameter packs/variadic generics (advanced; not covered here).
Sequence vs Collection#
Sequence: single-pass iteration guaranteed; may be destructive. Use when you don’t need indices or multiple passes.Collection: multi-pass with stable indices (startIndex/endIndex). Prefer for in-memory data you traverse multiple times.
map/compactMap/flatMap: convert, filter nils, flatten.filter: keep matching elements; be mindful of allocation on large data.reduce: combine into a single value; prefer reduce(into:) to avoid intermediate allocations.
1
2
3
4
| let upper = names.map { $0.uppercased() }
let numbers = strings.compactMap(Int.init)
let flattened = [[1,2],[3]].flatMap { $0 }
let counts = words.reduce(into: [:]) { $0[$1, default: 0] += 1 }
|
Lazy Views#
- Use
.lazy to defer work and reduce intermediate allocations, especially after filters and maps chained together.
1
| let firstBig = numbers.lazy.filter { $0 > 1000 }.first
|
Slicing and Subsequence#
- Slices (
ArraySlice, Substring) share storage with the base collection; copy to Array/String if you need long-term storage.
1
2
| let slice = array[2...] // ArraySlice
let copy = Array(slice) // makes an owned copy
|
Sorting and Searching#
sorted() returns a new array; sort() mutates in-place (more memory efficient).- For membership checks on large datasets, consider
Set or Dictionary over linear contains.
- Prefer
reserveCapacity on arrays and dictionaries when size is known to reduce reallocations. - For hot paths, avoid repeated
removeFirst() on arrays (O(n)); use indices or popLast() where order permits.
Algorithms to Remember#
zip to iterate pairs; stride(from:to:by:) for steps; prefix/while, drop/while for stream-like processing.grouping via Dictionary(grouping:by:); chunks manually via stride or rolling indices.
Testing#
- Add property-based checks (if available) for algorithms to ensure invariants (e.g., sorted output length matches input).
- Benchmark critical paths with
measure in XCTest or simple timing helpers; ensure lazy vs eager choices are intentional.