Перебор словаря
Вернёмся к телефонной книге. Иногда нужен не один номер, а вся книга сразу: например, чтобы напечатать все контакты. Бумажную книгу вы листали бы страницу за страницей и читали строку за строкой. Словарь тоже можно пройти целиком, но с одной оговоркой о порядке.
Перебор пар
Цикл for-in проходит словарь пара за парой. Каждая пара — кортеж из ключа и значения, и в заголовке цикла его сразу раскладывают на два имени:
let phones = ["Anna": "555-1234", "Boris": "555-9876", "Vera": "555-0000"]
for (name, phone) in phones {
print(name, phone)
}Давайте разберём программу по строкам:
- Первая строка создаёт словарь из трёх пар: ключ — имя, значение — номер.
for (name, phone) in phonesна каждой итерации берёт одну пару: ключ попадает вname, значение — вphone.print(name, phone)печатает имя и номер через пробел.
Программа печатает три строки, по одной на пару. В каком порядке — заранее неизвестно. Запустите её два-три раза, и строки могут выйти в другом порядке: при одном запуске первой идёт Анна, при следующем — Борис.
Это та неточность картинки, о которой шла речь в прошлом уроке: в бумажной книге имена идут по алфавиту. Словарь раскладывает пары так, чтобы быстро находить ключ, а Swift выбирает раскладку заново при каждом запуске программы. Поэтому программа никогда не должна полагаться на порядок пар в словаре.
Если имя или номер в цикле не нужны, вместо них пишут _: for (_, phone) in phones.
Ключи по алфавиту
Когда порядок нужен, его задают сами. phones.keys — все ключи словаря, а sorted() возвращает их массивом по возрастанию. Строки при этом идут по алфавиту, только заглавные латинские буквы стоят раньше строчных:
for name in phones.keys.sorted() {
print(name, terminator: " ") // Anna Boris Vera
}Теперь имена идут по алфавиту при каждом запуске: цикл проходит по отсортированному массиву, а не по самому словарю. Номер для каждого имени достают поиском: phones[name] ?? "none". phones.values даёт все значения словаря без ключей, тоже без порядка.
Частая ошибка
Номер достали поиском, но не открыли коробку:
for name in phones.keys.sorted() {
print(name, phones[name]) // ✗
}warning: expression implicitly coerced from 'String?' to 'Any'Это предупреждение, поэтому программа запустится. Но вместо Anna 555-1234 цикл напечатает Anna Optional("555-1234"), и так в каждой строке. Имя взято из ключей того же словаря, но компилятор этого не учитывает: поиск по ключу всегда даёт опционал. Откройте коробку: phones[name] ?? "none".
Главное
for (key, value) in dictперебирает пары, но их порядок не фиксирован и может меняться от запуска к запуску.- Нужен порядок — перебирайте
dict.keys.sorted()и доставайте значение поиском по ключу. - Поиск даёт опционал, даже когда ключ взят из того же словаря: откройте его через
??.