Overview

These methods live on Sequence and Collection, so they work on Array, Set, Dictionary, String, and your own conforming types. Non-mutating names (sorted) pair with mutating ones (sort). Without .lazy, each step builds an intermediate array. Value semantics are covered in swift-protocols.

Transform

Use compactMap to drop nil and reduce(into:) to build collections.

MethodReturnsNotes
map { }[T]Same count.
compactMap { }[T]Maps and drops nil.
flatMap { }[T]Maps to sequences and flattens one level.
filter { }[Element]Keeps elements where the closure is true.
reduce(0) { }ResultFold; always give an initial value.
reduce(into: [:]) { }ResultMutates the accumulator in place; no copy per step.
let nums = [1, 2, 3, 4, 5]
nums.map { $0 * 2 }                       // [2, 4, 6, 8, 10]
nums.filter { $0.isMultiple(of: 2) }      // [2, 4]
nums.reduce(0, +)                         // 15
["1", "x", "3"].compactMap { Int($0) }    // [1, 3]
let freq = nums.reduce(into: [Int: Int]()) { $0[$1, default: 0] += 1 }

Sort and order

Use sorted for a copy and sort for in-place.

MethodMutatesNotes
sorted(), sorted(by:)noNeeds Comparable or a closure.
sort(), sort(by:)yesOn mutable random-access collections such as Array.
reversed()noO(1) ReversedCollection view; wrap in Array(...) for a copy.
shuffled()noNew random order.
users.sorted { ($0.lastName, $0.firstName) < ($1.lastName, $1.firstName) }   // tuple comparison

Use contains(where:) and first(where:) instead of filtering then indexing.

MethodReturns
contains(x), contains { }Bool (contains(x) needs Equatable).
first, last, first { }, last { }Element?
firstIndex(of:), firstIndex { }Index?
min(), max(), min(by:), max(by:)Element?

Iterate

Use for ... in when you need an early exit.

MethodNotes
forEach { }Side effects; return only skips to the next element.
enumerated()(offset, element) pairs; offsets start at 0, they are not collection indices.
zip(a, b)Pairs elements; stops at the shorter sequence.
joined(), joined(separator:)Flatten sequences / join strings.

Dictionary

Use mapValues and Dictionary(grouping:) instead of manual loops.

OperationSyntax
Filterdict.filter { $0.value >= 80 } returns [K: V].
Map valuesdict.mapValues { $0 + 10 }, dict.compactMapValues { Int($0) }
GroupDictionary(grouping: users, by: { $0.department }) returns [K: [V]].
Mergedict.merging(other) { _, new in new } resolves key conflicts.
Default read/writedict[key, default: 0] += 1

Lazy

Put .lazy first to compute only the elements you consume.

let firstFive = (1...1_000_000).lazy
    .map { $0 * $0 }
    .filter { $0.isMultiple(of: 3) }
    .prefix(5)
Array(firstFive)

Gotchas

Avoid these; each copies data, hides a mismatch, or cannot exit early.

GotchaFix
forEach cannot break or continue.Use a for ... in loop.
reduce with an array or dictionary accumulator copies it each step.Use reduce(into:).
reversed() is a view, not an Array.Wrap it: Array(a.reversed()).
zip hides length mismatches.Assert equal counts first if they must match.
Array.contains is O(n).Convert to a Set before repeated membership checks.
flatMap on optionals was renamed compactMap in Swift 4.1.Use compactMap to drop nil.