Массив и индексы
Чему вы научитесь:
- создавать массивы и читать элементы по индексу, который начинается с нуля;
- добавлять, вставлять, удалять и искать элементы и объяснять, почему массив через
letне меняется; - перебирать массив в цикле, с номерами элементов и без них, и сортировать его;
- предсказывать, что станет с массивом после того, как его присвоили другой переменной.
![Ряд из четырёх шкафчиков; дверца a[0] закрыта, а дверца a[1] открыта и внутри посылка](/course-covers/swift-beginners/09-arrays.webp)
Представьте ряд шкафчиков в раздевалке бассейна. Шкафчики стоят вплотную друг к другу, на каждой дверце написан номер, и в каждом лежит одна вещь. Чтобы забрать вещь, не нужно помнить, как она называется: достаточно знать номер шкафчика.
Теперь задача на программирование. Учитель хранит оценки за три контрольные. Можно завести три константы: score1, score2 и score3. А если контрольных тридцать? Тридцать имён неудобно и объявлять, и перебирать.
Для таких данных есть массив — ряд значений одного типа под одним именем. Каждое значение в ряду называют элементом массива. Вот массив из трёх оценок:
let scores = [7, 9, 4]
print(scores) // [7, 9, 4]
print(scores[0]) // 7
print(scores[2]) // 4
print(scores.count) // 3Давайте разберём программу по строкам:
let scores = [7, 9, 4]заводит массивscores: элементы перечислены через запятую в квадратных скобках.print(scores)печатает весь массив, тоже в квадратных скобках.scores[0]— элемент из шкафчика с номером0, то есть первый:7.scores[2]— элемент из шкафчика с номером2, то есть третий:4.scores.count— сколько элементов в массиве:3.
Индекс начинается с нуля
Номер элемента в массиве называют индексом. Это обычное целое число типа Int, и его пишут в квадратных скобках сразу после имени массива: scores[0].
У строки запись s[0] не компилируется: символы занимают разное число байтов, и Swift требует индекс String.Index. У массива все элементы одного типа и занимают одинаковое число байтов, поэтому номер сразу даёт место элемента.
Индекс показывает, на сколько шагов элемент отстоит от начала ряда. Первый элемент стоит в самом начале, поэтому у него индекс 0. Отсюда два правила:
- у первого элемента индекс
0; - у последнего —
count - 1: в массиве из трёх элементов это2.
Здесь картинка со шкафчиками неточна. В раздевалке номера обычно начинают с единицы, а в массиве — с нуля. Зато индексы, как и шкафчики, идут подряд, без пропусков: от 0 до count - 1.
Тип массива
Все элементы массива одного типа, и тип массива пишут в квадратных скобках: [Int] — массив целых чисел, [String] — массив строк. Массив [1, "a"] не скомпилируется: число и строка в один ряд не встают.
Завести массив можно тремя способами.
Значения в скобках
Для [7, 9, 4] Swift сам выводит тип по элементам. Здесь все элементы целые, поэтому у scores тип [Int].
Аннотация типа
Аннотация из темы про переменные работает и с массивами: let prices: [Double] = [5, 7.5]. Целое 5 становится 5.0, потому что массив хранит дробные числа.
Пустой массив
Пустой массив пишут как [String](): тип в квадратных скобках и пара круглых скобок после него. Тип здесь обязателен: элементов нет, и выводить его не из чего. Запись let names = [] не скомпилируется с ошибкой empty collection literal requires an explicit type. С аннотацией пустые скобки работают: let names: [String] = [].
let prices: [Double] = [5, 7.5]
print(prices) // [5.0, 7.5]
let names = [String]()
print(names.count, names.isEmpty) // 0 trueisEmpty отвечает на вопрос «массив пуст?» и даёт Bool. У пустого массива count равен 0, а isEmpty — true. Пустоту в Swift принято проверять через isEmpty: так код читается яснее, чем count == 0.
Частая ошибка
Последний элемент попытались взять по индексу count:
print(scores[scores.count]) // ✗Fatal error: Index out of rangeПрограмма компилируется, но при запуске аварийно завершается на этой строке. В массиве три элемента с индексами 0, 1 и 2, а scores.count равен 3. Шкафчика с номером 3 в ряду нет.
Swift проверяет каждый индекс во время работы программы. Если такого индекса в массиве нет, программа останавливается, а не возвращает выдуманное значение. На собеседовании часто спрашивают, что будет при выходе за границы массива. Ответ для Swift: аварийное завершение с сообщением Index out of range.
Последний элемент лежит по индексу count - 1:
print(scores[scores.count - 1]) // 4Главное
- Массив хранит ряд значений одного типа под одним именем, а его тип пишут как
[Int]или[String]. - Индекс первого элемента —
0, последнего —count - 1. count— число элементов,isEmpty— пуст ли массив; пустому массиву нужен тип:[String]().- Индекс за границами массива компилируется, но аварийно завершает программу:
Index out of range.