Перейти к содержанию
Educora
Средний18 мин5 / 14

Коллекции: массивы, словари, множества

Храни много значений в массивах, словарях и множествах, изменяй их и обрабатывай одной строкой с помощью `map`, `filter` и `reduce`.

Проверь себя
В этом уроке ты узнаешь
  • Создавать массив, обращаться к элементам по индексу, добавлять и удалять их
  • Работать со словарями и множествами и выбирать подходящую коллекцию
  • Преобразовывать коллекции с помощью map, filter и reduce

В музыкальном приложении плейлист хранит песни в определённом порядке, телефонная книга находит номер по имени, а в списке «понравилось» одна и та же фотография не может оказаться дважды. Для этих трёх ситуаций в Swift есть три коллекции: массив (Array), словарь (Dictionary) и множество (Set).

Массивы

Массив — упорядоченный список значений одного типа, записанный в квадратных скобках. У каждого элемента есть индекс, и счёт начинается с 0: первый элемент — fruits[0]. Тип массива записывается как [String], [Int]. Массив, объявленный через var, можно менять, а массив let — нет.

Swift
var fruits = ["apple", "banana", "cherry"]
print(fruits)
print(fruits[0])
print(fruits.count)

fruits.append("pear")
fruits.insert("kiwi", at: 1)
print(fruits)

fruits.remove(at: 2)
print(fruits)
print(fruits.contains("pear"))
print(fruits.first ?? "empty")
Ожидаемый результат
["apple", "banana", "cherry"]
apple
3
["apple", "kiwi", "banana", "cherry", "pear"]
["apple", "kiwi", "cherry", "pear"]
true
apple

first и last возвращают опционалы, потому что массив может быть пустым. Для перебора массива используют for-in, а если нужны и индекс, и значение — enumerated(). sorted() возвращает новый отсортированный массив, а max() и min() — наибольший и наименьший элемент (в виде опционала).

Swift
let scores = [85, 92, 78]
for (index, score) in scores.enumerated() {
    print("\(index + 1). \(score)")
}
print(scores.sorted())
print(scores.max() ?? 0)

let empty: [Int] = []
print(empty.isEmpty)
Ожидаемый результат
1. 85
2. 92
3. 78
[78, 85, 92]
92
true

Словари

Словарь хранит пары ключ: значение и находит значение не по индексу, а по ключу. Его тип записывается как [String: String]. Значение, прочитанное по ключу, всегда опционально, потому что такого ключа может не быть, — здесь очень пригодится ??. Если присвоить ключу nil, пара удаляется.

Swift
var capitals = ["Azerbaijan": "Baku", "Georgia": "Tbilisi"]
capitals["Japan"] = "Tokyo"

print(capitals["Azerbaijan"] ?? "unknown")
print(capitals["France"] ?? "unknown")
print(capitals["Japan"])

capitals["Georgia"] = nil
print(capitals.count)

for country in capitals.keys.sorted() {
    print("\(country) -> \(capitals[country] ?? "")")
}
Ожидаемый результат
Baku
unknown
Optional("Tokyo")
2
Azerbaijan -> Baku
Japan -> Tokyo

Одно из самых полезных применений словаря — подсчёт. Класс голосовал за любимое животное — сколько голосов получило каждое?

Swift
let votes = ["cat", "dog", "cat", "fish", "cat", "dog"]
var counts: [String: Int] = [:]

for vote in votes {
    counts[vote, default: 0] += 1
}

for animal in counts.keys.sorted() {
    print(animal, counts[animal, default: 0])
}
Ожидаемый результат
cat 3
dog 2
fish 1

Множества

Множество (Set) — набор неповторяющихся значений без порядка. Если добавить одно и то же значение дважды, оно сохранится один раз. Множества очень быстро проверяют, есть ли в них элемент, и поддерживают пересечение (intersection) и объединение (union), как в математике.

Swift
var visited: Set = ["Baku", "Ganja", "Baku", "Shaki"]
print(visited.count)

visited.insert("Lankaran")
print(visited.contains("Ganja"))

let friendVisited: Set = ["Baku", "Quba"]
print(visited.intersection(friendVisited).sorted())
print(visited.union(friendVisited).sorted())
Ожидаемый результат
3
true
["Baku"]
["Baku", "Ganja", "Lankaran", "Quba", "Shaki"]
КоллекцияПорядокПовторыКогда выбирать
Массив [T]естьможнокогда важен порядок: плейлист, очередь
Словарь [K: V]нетключи не повторяютсяпоиск по ключу: контакты, цены
Множество Set<T>нетнельзяуникальность и быстрая проверка: теги, посещённые города

`map`, `filter` и `reduce`

Для обработки коллекций без циклов есть три мощных метода. map преобразует каждый элемент и создаёт новый массив, filter оставляет только элементы, подходящие под условие, а reduce сворачивает все элементы в одно значение. Код в фигурных скобках — это замыкание (closure), а $0 — текущий элемент; замыкания подробно разберём в следующем уроке.

Swift
let prices = [4, 12, 7, 20]

let doubled = prices.map { $0 * 2 }
let cheap = prices.filter { $0 < 10 }
let total = prices.reduce(0, +)

print(doubled)
print(cheap)
print(total)
print(prices.filter { $0 >= 10 }.reduce(0, +))

let names = ["aysel", "murad"]
print(names.map { $0.uppercased() })
Ожидаемый результат
[8, 24, 14, 40]
[4, 7]
43
32
["AYSEL", "MURAD"]

Главное

  • Массив упорядочен, индексы начинаются с 0; выход за границы роняет программу.
  • Словарь находит значение по ключу и возвращает опционал; присваивание nil удаляет пару.
  • У словарей и множеств нет порядка — для стабильного результата используй sorted().
  • Множество хранит неповторяющиеся значения и умеет intersection и union.
  • map преобразует, filter отбирает, reduce сворачивает.

Проверь себя

Вопросов: 10. Каждый правильный ответ приносит XP.

1 / 10
Если let a = [10, 20, 30], чему равно a[1]?