swift

Словарь (Dictionary) в Swift 📖

Dictionary — это неупорядоченная коллекция, которая хранит пары «ключ — значение».

Каждый ключ в словаре уникален, а значения могут повторяться.

// Сравним уже известные вам Массив и Словарь:
let fruitsArray = ["Яблоко 🍎", "Банан 🍌", " Клубничка 🍓"] // Список элементов
let fruitsDictionary = [
	"apple": "Яблоко 🍎", 
	"banana": "Банан 🍌", 
	"strawberry": "Клубничка 🍓"
] // Пары "ключ: значение"

Что вы изучите 🎯

Тема Описание
🎯 Основы Что такое Dictionary и чем он отличается от массива
🤔 Применение Когда удобно использовать словарь вместо других коллекций
🏗️ Создание Как объявлять и инициализировать Dictionary
Добавление Как добавлять новые пары (ключ-значение) в словарь
🗑️ Удаление Как удалять элементы из словаря
🔍 Доступ Как получать значения по ключу
🔄 Перебор Как проходить по всем элементам словаря
🛠️ Изменение Как обновлять значения
⚠️ Опционалы Почему словари всегда возвращают опциональные значения
🧩 Сложные типы Какие типы могут быть ключами

Что такое Dictionary? 🧐

Представьте, что у вас есть телефонная книга 📒:

Телефонная книга содержит:
- "Мама" 👩  "+7-912-345-67-89"
- "Папа" 👨  "+7-915-678-90-12"
- "Друг" 🧑  "+7-903-123-45-67"

Главные правила такой книги:

  1. 🏷️ У каждого контакта уникальное имя (не может быть двух “Мам”)
  2. 🔑 По имени можно быстро найти номер (не нужно листать всю книгу)
  3. 📱 У каждого имени есть значение — номер телефона

Dictionary vs Array

Характеристика Массив (Array) Словарь (Dictionary)
Доступ По индексу (array[2]) По ключу (dict["ключ"])
Тип индекса/ключа Только Int Любой Hashable тип (String, Int, и т.д.)
Дубликаты ✅ Разрешены ❌ Ключи уникальны, значения могут повторяться
Скорость поиска 🐢 Медленная (O(n)) ⚡ Мгновенная (O(1))
Аналогия Полка с книгами 📚 Телефонная книга 📒
Порядок элементов ✅ Сохраняется ❌ Не гарантируется

Пример в коде:

// Массив — ищем по позиции
let playlist = ["Песня 1", "Песня 2", "Песня 3"]
print(playlist[1])  // "Песня 2" (знаем индекс)

// Словарь — ищем по ключу
let phoneBook = [
    "Мама": "👩 +7-912-345-67-89", 
    "Папа": "👨 +7-915-678-90-12"
]
print(phoneBook["Мама"]!)  // "👩 +7-912-345-67-89" (знаем имя)

Когда использовать Dictionary 👍

Ситуация Пример Почему Dictionary?
Поиск по идентификатору Найти пользователя по ID Мгновенный доступ по ключу
Настройки / Конфиги Параметры приложения Удобно хранить пары "volume": 44
Кэширование данных Временное хранение результатов Быстрый доступ по ключу
Подсчет частоты Сколько раз встречается слово Ключ — слово, значение — счетчик
Связанные данные Страна → столица, Код → название Естественное представление связей
API ответы JSON данные Прямая аналогия со структурой JSON

На первый взгляд, представленные выше примеры кажутся неочевидными.

Это связано с недостатком опыта, не волнуйтесь – по мере продвижения в мире программирования, вы прекрасно разберётесь в ситуациях, в которых без Словаря не обойтись.

Пример из жизни:

// ❌ Плохо: используем массив для поиска по ID
var usersArray: [(id: Int, name: String)] = []
// Чтобы найти пользователя с id = 101, нужно перебрать весь массив

// ✅ Оптимально: используем словарь
var usersDict: [Int: String] = [
    101: "Анна", 
    102: "Иван", 
    103: "Ольга"
]
let userName = usersDict[101]  // Мгновенно! "Анна"

Создание Dictionary 🏗️

Пустой словарь

var emptyNumbers: [String: Double] = [:] // Пустой словарь [String: Double]

Словарь с элементами

// Строковые ключи и строковые значения
var capitals: [String: String] = [
    "Россия": "Москва",
    "Франция": "Париж", 
    "Япония": "Токио"
]

// Целочисленные ключи и строковые значения
var httpStatus: [Int: String] = [
    200: "OK",
    404: "Not Found",
    500: "Internal Server Error"
]

// Без указания типа (Swift сам разберётся, не маленький уже)
let scores = [
    "Анна": 95, 
    "Иван": 87, 
    "Ольга": 92
]  // Тип: [String: Int]

let vs var

// var — можно изменять
var mutableDict = ["a": 1, "b": 2]
mutableDict["c"] = 3  // ✅ Работает!

// let — нельзя изменять
let immutableDict = ["a": 1, "b": 2]
immutableDict["c"] = 3  // ❌ Ошибка!

Доступ к элементам 🔍

let fruitsDictionary = [
	"apple": "Яблоко 🍎", 
	"banana": "Банан 🍌", 
	"strawberry": "Клубничка 🍓"
]

Получение значения по ключу

// Простой доступ (возвращает опционал, так как, а вдрух элемента по ключу нет ?)
let strawberry = fruits["strawberry"] // Optional("Клубничка 🍓")
let mango = fruits["mango"] // nil (ключа нет)

// С развертыванием опционала
if let fruit = fruits["banana"] {
    print("Нашли: \(fruit)")  // Нашли: Банан 🍌
}

// Со значением по умолчанию
let pear = fruits["pear", default: "Груша 🍐"]  // "Груша 🍐" (ключа нет, вернули default)

⚠️ Важно! Dictionary всегда возвращает опциональное значение, потому что ключа может не существовать!

Добавление и изменение элементов ➕

var fruitsDictionary = [
	"apple": "Яблоко 🍎", 
	"banana": "Банан 🍌", 
	"strawberry": "Клубничка 🍓"
]

Добавление новой пары

fruitsDictionary["cherry"] = "Черешня 🍒" // Добавили ключ-значение для Черешни

Изменение существующего значения

fruitsDictionary["apple"] = "Тыблоко 🍏"  // Было "Яблоко 🍎", стало "Тыблоко 🍏"

Удаление элементов 🗑️

Удаление по ключу

// Способ 1: присвоить nil
fruitsDictionary["banana"] = nil // Банана теперь нет

Очистка словаря

fruitsDictionary.removeAll() // [:]

Перебор элементов 🔄

let scores = ["Анна": 95, "Иван": 87, "Ольга": 92, "Петр": 78]

Перебор по парам ключ-значение

for (name, score) in scores {
    print("\(name): \(score) баллов")
}
// Анна: 95 баллов
// Иван: 87 баллов
// Ольга: 92 баллов
// Петр: 78 баллов

Перебор только ключей

for name in scores.keys {
    print("Студент: \(name)")
}
// Студент Анна
// Студент Иван
// Студент Ольга
// Студент Петр

Перебор только значений

for score in scores.values {
    print("Балл: \(score)")
}
// Балл 95
// Балл 87
// Балл 92
// Балл 78

Массивы из ключей и значений

let names = Array(scores.keys)        // ["Анна", "Иван", "Ольга", "Петр"]
let allScores = Array(scores.values)  // [95, 87, 92, 78]

Полезные свойства и методы 📚

var dict = ["a": 1, "b": 2, "c": 3]
Свойство Описание Пример
count Количество элементов dict.count // 3
isEmpty Проверка на пустоту dict.isEmpty // false
keys Все ключи dict.keys // [“a”, “b”, “c”]
values Все значения dict.values // [1, 2, 3]
first Первый элемент (не гарантирован) dict.first // Optional((“a”, 1))

Сложные типы в Dictionary 🧱

Требование к ключам: Hashable

Чтобы тип мог быть ключом в словаре, он должен поддерживать протокол Hashable:

Пример со своей структурой

struct Person: Hashable {
    let id: Int
    let name: String
}

var personAges: [Person: Int] = [:]

let person1 = Person(id: 1, name: "Анна")
let person2 = Person(id: 2, name: "Иван")

personAges[person1] = 25
personAges[person2] = 30

print(personAges[person1]!)  // 25

Шпаргалка 📝

Действие Код Пояснение
Создать пустой словарь var dict: [String: Int] = [:] Пустой словарь
С данными let dict = ["a": 1, "b": 2] С двумя парами
Получить значение dict["a"] Optional(1)
С значением по умолчанию dict["c", default: 0] 0 (если ключа нет)
Добавить/обновить dict["c"] = 3 Добавляет или обновляет
Удалить dict["a"] = nil Удаляет пару
Количество dict.count Сколько элементов
Проверить пустоту dict.isEmpty true, если пусто

Частые ошибки новичков ⚠️

Ошибка 1: Забывают про опционалы

let dict = ["a": 1, "b": 2]
let value = dict["c"] + 5  // ❌ Ошибка! value — опционал

// ✅ Надо так:
if let value = dict["c"] {
    let result = value + 5
}
// Или так:
let result = (dict["c"] ?? 0) + 5

Ошибка 2: Пытаются изменить let-словарь

let dict = ["a": 1, "b": 2]
dict["c"] = 3  // ❌ Ошибка! let = неизменяемый

// ✅ Надо использовать var
var mutableDict = ["a": 1, "b": 2]
mutableDict["c"] = 3  // ✅ Работает!

Ошибка 3: Думают, что порядок сохранится

let dict = ["a": 1, "b": 2, "c": 3, "d": 4]
// Не надейтесь, что элементы будут в порядке a, b, c, d!
for (key, value) in dict {
    print("\(key): \(value)")  // Может быть: c: 3, a: 1, d: 4, b: 2
}

Когда что использовать? 🤔

Нужно Выбор Почему
Доступ по ключу Dictionary dict["ключ"] — мгновенно
Сохранить порядок Array У массива есть индексы
Уникальные ключи Dictionary Ключи всегда уникальны
Простой список Array Не нужны ключи
Связанные данные Dictionary Пары “ключ-значение”
Значение по индексу Array array[2] — легко

Проверь себя! ✍️

Вопрос 1

Что вернет fruits["mango"], если такого ключа нет в словаре?

Вопрос 2

Как добавить новую пару в словарь?

Вопрос 3

Какой тип данных может быть ключом в словаре?

Задание 🚀

  1. Создайте структуру, в которой будет храниться информации о студентах и их оценках
  2. Добавьте 2-3 студента, значения оценок выберите сами
  3. Добавьте оценки для каждого студента, ещё как минимум по одной
  4. Со звёздочкой Напишите функцию, которая принимает ID студента и возвращает его средний балл

Решение можете присылать сюда

Что дальше? 🚀

Поздравляю! Вы освоили Dictionary — мощный инструмент для хранения связанных данных. Теперь вы готовы к изучению:

Тема Описание
Множества (Set) Коллекции уникальных значений
Опционалы Безопасная работа с nil
Функции Создание и использование функций