Изменение массива
В прошлом уроке ряд шкафчиков был готов заранее. Но ряд можно и перестроить: пристроить шкафчик в конце, вставить новый в середину или убрать лишний.
Массив, объявленный через var, умеет то же самое. Эта программа меняет ряд оценок четыре раза и печатает его после каждого изменения:
var scores = [7, 9]
scores.append(4)
print(scores) // [7, 9, 4]
scores.insert(10, at: 0)
print(scores) // [10, 7, 9, 4]
let removed = scores.remove(at: 1)
print(removed, scores) // 7 [10, 9, 4]
scores[0] = 8
print(scores) // [8, 9, 4]Давайте разберём, что делает каждое изменение:
append(4)добавляет4в конец, и массив становится[7, 9, 4].insert(10, at: 0)вставляет10по индексу0, а остальные элементы сдвигаются вправо.remove(at: 1)убирает элемент с индексом1— это7— и возвращает его, поэтому7попадает в константуremoved.scores[0] = 8кладёт8на место10.
append, insert и remove — методы массива: их вызывают через точку после имени массива, как методы строк.
Четыре способа изменить массив
append — в конец
scores.append(4) добавляет элемент после последнего. count вырастает на единицу, а индексы старых элементов не меняются.
insert(_:at:) — по индексу
scores.insert(10, at: 0) ставит элемент на место с индексом 0. Все элементы с этого места сдвигаются на одну позицию вправо: 7 был по индексу 0, а стал по индексу 1. Индекс для вставки берут от 0 до count, и вставка по индексу count работает как append.
remove(at:) — убрать
scores.remove(at: 1) убирает элемент, и элементы справа от него сдвигаются влево, чтобы в ряду не осталось дыры. Метод возвращает удалённое значение: его можно сохранить, как removed в примере, а можно не использовать.
Присваивание по индексу
scores[0] = 8 заменяет элемент, а число элементов остаётся прежним. Так меняют только элемент, который уже есть. Индекс за границами массива и здесь, и в remove(at:) аварийно завершает программу.
Здесь картинка со шкафчиками неточна. На дверце шкафчика номер написан раз и навсегда, а в массиве после insert и remove индексы пересчитываются. Они всегда идут подряд, от 0 до count - 1.
Склейка через +
Оператор + склеивает два массива одного типа в новый массив. Исходные массивы он не меняет:
let more = scores + [5, 6]
print(scores.count, more.count) // 3 5В scores по-прежнему три элемента, а в новом массиве more — пять. Поэтому + работает и с массивами, объявленными через let.
Частая ошибка
Элемент добавили в массив, объявленный через let:
let days = [1, 2, 3]
days.append(4) // ✗error: cannot use mutating member on immutable value: 'days' is a 'let' constantПрограмма не компилируется. Массив через let — константа целиком: в нём нельзя добавить, вставить, удалить или заменить ни одного элемента. Замена по индексу даёт похожую ошибку: cannot assign through subscript: 'days' is a 'let' constant. Если ряд должен меняться, объявите его через var.
На собеседовании часто спрашивают, можно ли изменить массив, объявленный через let. Например, в JavaScript константа запрещает только связать имя с другим массивом, а сам массив менять можно. В Swift let замораживает и содержимое.
Главное
appendдобавляет в конец,insert(_:at:)вставляет по индексу, аremove(at:)удаляет элемент и возвращает его.- После вставки и удаления индексы пересчитываются и снова идут подряд с нуля.
+создаёт новый массив и не меняет исходные.- Массив через
letменять нельзя: ни добавить, ни удалить, ни заменить элемент.