Перейти к содержимому
Теория · Массивы · урок 1 из 8

Массив и индексы

Чему вы научитесь

Чему вы научитесь:

  • создавать массивы и читать элементы по индексу, который начинается с нуля;
  • добавлять, вставлять, удалять и искать элементы и объяснять, почему массив через let не меняется;
  • перебирать массив в цикле, с номерами элементов и без них, и сортировать его;
  • предсказывать, что станет с массивом после того, как его присвоили другой переменной.
Ряд из четырёх шкафчиков; дверца a[0] закрыта, а дверца a[1] открыта и внутри посылка

Представьте ряд шкафчиков в раздевалке бассейна. Шкафчики стоят вплотную друг к другу, на каждой дверце написан номер, и в каждом лежит одна вещь. Чтобы забрать вещь, не нужно помнить, как она называется: достаточно знать номер шкафчика.

Теперь задача на программирование. Учитель хранит оценки за три контрольные. Можно завести три константы: score1, score2 и score3. А если контрольных тридцать? Тридцать имён неудобно и объявлять, и перебирать.

Для таких данных есть массив — ряд значений одного типа под одним именем. Каждое значение в ряду называют элементом массива. Вот массив из трёх оценок:

SWIFT
let scores = [7, 9, 4]
print(scores)        // [7, 9, 4]
print(scores[0])     // 7
print(scores[2])     // 4
print(scores.count)  // 3

Давайте разберём программу по строкам:

  1. let scores = [7, 9, 4] заводит массив scores: элементы перечислены через запятую в квадратных скобках.
  2. print(scores) печатает весь массив, тоже в квадратных скобках.
  3. scores[0] — элемент из шкафчика с номером 0, то есть первый: 7.
  4. scores[2] — элемент из шкафчика с номером 2, то есть третий: 4.
  5. 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] = [].

SWIFT
let prices: [Double] = [5, 7.5]
print(prices)  // [5.0, 7.5]
let names = [String]()
print(names.count, names.isEmpty)  // 0 true

isEmpty отвечает на вопрос «массив пуст?» и даёт Bool. У пустого массива count равен 0, а isEmpty — true. Пустоту в Swift принято проверять через isEmpty: так код читается яснее, чем count == 0.

Частая ошибка

Последний элемент попытались взять по индексу count:

SWIFT
print(scores[scores.count]) // ✗
TEXT
Fatal error: Index out of range

Программа компилируется, но при запуске аварийно завершается на этой строке. В массиве три элемента с индексами 0, 1 и 2, а scores.count равен 3. Шкафчика с номером 3 в ряду нет.

Swift проверяет каждый индекс во время работы программы. Если такого индекса в массиве нет, программа останавливается, а не возвращает выдуманное значение. На собеседовании часто спрашивают, что будет при выходе за границы массива. Ответ для Swift: аварийное завершение с сообщением Index out of range.

Последний элемент лежит по индексу count - 1:

SWIFT
print(scores[scores.count - 1])  // 4

Главное

  • Массив хранит ряд значений одного типа под одним именем, а его тип пишут как [Int] или [String].
  • Индекс первого элемента — 0, последнего — count - 1.
  • count — число элементов, isEmpty — пуст ли массив; пустому массиву нужен тип: [String]().
  • Индекс за границами массива компилируется, но аварийно завершает программу: Index out of range.