# Arrays, Dictionaries, Sets and Functional Operations — Swift

Source: https://www.skillbyai.com/en/swift/o-collections

> Use Swift collections, value semantics and map, filter and reduce.

## Collections as values

Swift's main collections are **`Array`** (ordered), **`Dictionary`** (key-value, unordered) and **`Set`** (unique, unordered). They are **value types**: assigning an array to another variable creates an independent copy, implemented efficiently with **copy-on-write**, so the actual copying happens only when one copy is modified. Collections declared with `let` are fully immutable. Accessing an array index out of range **traps** at run time; use `indices.contains(i)` or safe helpers when the index may be invalid. Dictionary subscripts return optionals, and `dict[key, default: 0] += 1` makes counting easy. Higher-order functions express transformations clearly: **`map`**, **`filter`**, **`reduce`**, **`compactMap`** (drops nils), **`flatMap`**, **`sorted(by:)`**, **`first(where:)`**, **`contains(where:)`**, **`allSatisfy`** and **`Dictionary(grouping:by:)`**. Sets offer `union`, `intersection`, `subtracting` and O(1) average membership tests. Elements of sets and dictionary keys must be **`Hashable`**.

## Collections in everyday code

Grouping, filtering, counting and set operations.

```swift
struct Order { let id: String; let city: String; let total: Double }

let orders = [
    Order(id: "o1", city: "Pune",  total: 1200),
    Order(id: "o2", city: "Delhi", total: 300),
    Order(id: "o3", city: "Pune",  total: 800),
]

let bigOrders = orders.filter { $0.total >= 500 }.sorted { $0.total > $1.total }
let revenue = orders.reduce(0) { $0 + $1.total }
let byCity = Dictionary(grouping: orders, by: \.city)          // [String: [Order]]
let cityTotals = byCity.mapValues { $0.reduce(0) { $0 + $1.total } }

var wordCounts: [String: Int] = [:]
for word in "to be or not to be".split(separator: " ") {
    wordCounts[String(word), default: 0] += 1
}

let quantities = ["3", "x", "5"].compactMap { Int($0) }        // [3, 5]

let morning: Set = ["Asha", "Ravi", "Meera"]
let evening: Set = ["Ravi", "Kabir"]
let both = morning.intersection(evening)                      // ["Ravi"]

var copy = orders          // value semantics: an independent copy (copy-on-write)
copy.removeAll()           // orders is unchanged
```

## Out-of-range indices trap

`array[5]` on a three-element array crashes immediately. When an index comes from outside your control, check `array.indices.contains(i)` first or use `first`, `last` and `first(where:)`, which return optionals.

**Quiz:** What does copy-on-write mean for Swift arrays?

- [x] Copies share storage until one of them is modified, then the data is actually copied
- [ ] Arrays cannot be copied
- [ ] Every assignment copies all elements immediately
- [ ] Arrays are reference types

*Answer:* Copies share storage until one of them is modified, then the data is actually copied. Copy-on-write gives value semantics with the efficiency of shared storage.
