JavaRush /Курсы /Swift SELF /Создание массивов: Array<Element>

Создание массивов: Array<Element>

Swift SELF
11 уровень , 1 лекция
Открыта

1. Что такое Array и какие у него правила

Если вы только начинаете, кажется, что переменных достаточно: ну сделаю book1, book2, book3 — и готов «список книг». Но это быстро превращается в головную боль: как добавить четвёртую книгу, как перебрать все, как найти «самую короткую строку»? Массив решает эту проблему: он хранит много значений одного типа, в порядке добавления, и позволяет писать универсальный код.

Представьте, что вы ведёте маленькую консольную программу «Список чтения». Вчера вы могли хранить одну книгу в String. Сегодня вы хотите хранить список названий книг. Вот тут Array и выходит на сцену — как полка, на которую можно поставить не одну книгу, а много.

Когда вы слышите слово «массив», важно не утонуть в терминах и держать в голове две простые мысли.

  • Первая: массив хранит элементы в порядке.
  • Вторая: все элементы массива имеют один и тот же тип. Никаких «тут Int, тут String, а тут ещё котик» — котик будет позже, когда вы изучите другие инструменты (и, надеюсь, не в продакшене).

То есть массив можно описать так: «упорядоченная коллекция значений одного типа». Порядок важен, потому что «первый», «второй», «третий» — это реальная характеристика массива. И позже мы будем получать элементы по позиции (по индексу), перебирать их циклом и изменять.

Индекс в массиве

Мало знать, что у вас есть массив, нужно еще и уметь работать с его элементами. Чтобы получить элемент из массива, нужно знать его позицию. Эта позиция называется индексом.

Индексы в Swift (как и во многих языках программирования) начинаются с нуля, а не с единицы. Это может сначала выглядеть непривычно, но быстро становится естественным.

Представьте массив книг:

let books = ["Dune", "Foundation", "The Hobbit"] // три стоки упакованные в виде массива

Если пронумеровать элементы, получится так:

Индекс Элемент
0
"Dune"
1
"Foundation"
2
"The Hobbit"

То есть:

  • первый элемент имеет индекс 0
  • второй — 1
  • третий — 2

Количество элементов можно узнать через count. А последний индекс всегда равен count - 1.

print(books.count) // 3

Схема индексов

flowchart LR
    A["0 Dune"] --> B["1 Foundation"]
    B --> C["2 The Hobbit"]

Главное правило: индекс всегда должен находиться в диапазоне от 0 до count - 1. Если попытаться обратиться к несуществующему индексу, программа завершится с ошибкой.

Например, у массива из 3 элементов индекс 3 уже не существует.

var books = ["Dune", "Foundation", "The Hobbit"]
books[1] = "The Hitchhiker's Guide to the Galaxy"

print(books[0]) // Dune
print(books[1]) // The Hitchhiker's Guide to the Galaxy
print(books[2]) // The Hobbit

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

2. Создаём массивы: основные способы

Литерал массива

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

let scores = [10, 20, 30]
print(scores) // [10, 20, 30]

Здесь scores — массив целых чисел. Обратите внимание: мы не писали тип явно. Swift увидел элементы 10, 20, 30 и сделал вывод: «ага, это Int, значит массив [Int]».

Пример со строками:

let authors = ["Le Guin", "Tolkien", "Asimov"]
print(authors) // ["Le Guin", "Tolkien", "Asimov"]

И снова тип выводится автоматически: элементы — строки, значит массив [String].

Вывод типов для массивов

Вывод типов для массива работает прямолинейно: Swift смотрит на элементы в квадратных скобках и пытается понять, какого они типа. Если все элементы одного типа — отлично, тип массива определён.

Сложность начинается, когда элементы выглядят «похожими», но на самом деле имеют разные типы. Например, 1 — это Int, а 1.5 — это уже Double. В одном массиве их вместе держать нельзя, потому что массив должен иметь один тип элементов.

Решение: сделать массив Double, если привести целые к Double.

let measurements: [Double] = [1.0, 1.5, Double(2)]
print(measurements) // [1.0, 1.5, 2.0]

Здесь мы явно подсказали тип массива ([Double]), и Swift согласился. Если бы мы написали [1, 1.5, 2], компилятор бы остановил нас и сказал: «определись, что ты хочешь хранить». И это хорошо: компилятор не даёт сделать программу «почти работающей», но с сюрпризом в рантайме.

Небольшая схема того, как обычно работает вывод типа:

flowchart TD
    A["Пишем литерал массива: [ ... ]"] --> B["Swift смотрит на элементы"]
    B --> C{"Все элементы одного типа?"}
    C -->|Да| D["Тип массива выводится автоматически"]
    C -->|Нет| E["Нужна подсказка: явный тип или преобразование"]

Пустой массив и почему [] недостаточно

Самый частый «новичковый» сюрприз: вы хотите начать со списка, в котором пока ничего нет. Логика простая: пишем []. Но Swift не телепат (по крайней мере, официально), и ему нужно понимать, какие элементы будут в массиве.

Так делать нельзя (не компилируется):

  • let items = [] — компилятор не знает, что это за элементы.

Правильный способ — дать тип явно. Есть несколько равнозначных вариантов.

Вариант 1: указать тип слева:

let books: [String] = []
print(books) // []

Вариант 2: использовать «пустой конструктор» типа массива:

let ids = [Int]()
print(ids) // []

Вариант 3: через форму Array<T>():

let flags = Array<Bool>()
print(flags) // []

Все три варианта создают пустой массив. Отличается только то, как именно вы объясняете Swift, что будет храниться внутри.

Две записи типа массива: [Int] и Array<Int>

В Swift есть две равноправные формы записи типа массива. Короткая и самая популярная — [Int], [String], [Bool]. Длинная и более «общая» — Array<Int>, Array<String>. Это один и тот же тип, просто разная запись.

Полезно понимать обе формы, потому что в документации и в сигнатурах вы встретите Array<Element> довольно часто. Вообще Array — это обобщённый (generic) тип, и запись Array<String> как раз показывает: «внутри лежит String».

Примеры, которые компилируются одинаково:

let a: [Int] = [1, 2, 3]
let b: Array<Int> = [1, 2, 3]

print(a) // [1, 2, 3]
print(b) // [1, 2, 3]

Иногда длинная форма помогает «не путаться глазами», когда тип становится сложным. Но на базовом уровне чаще всего достаточно короткой формы [T].

let vs var при создании массива

С массивами работает то же правило, что и с любыми значениями в Swift.

Если вы объявили массив через let, вы получаете константу: сам массив нельзя менять (его состав и порядок). Если через var, массив можно изменять.

Сегодня мы ещё не используем append, insert и remove (это будет чуть позже), поэтому разницу почувствуем через простую вещь — переприсваивание.

var tags = ["swift", "basics"]
print(tags) // ["swift", "basics"]

tags = ["swift", "basics", "arrays"]
print(tags) // ["swift", "basics", "arrays"]

А теперь константа:

let roles = ["admin", "editor"]
print(roles) // ["admin", "editor"]

roles можно печатать, передавать в функции, читать, но нельзя менять.

Интуитивная аналогия: let — это «список, который вы распечатали и заламинировали». Читать можно, дописать маркером уже нельзя. var — «список в заметках», который можно редактировать.

Мини-проект: заготовка ReadingList

Чтобы примеры не были набором случайных чисел, начнём мини-проект этого дня — консольную заготовку «ReadingList». Пока она максимально простая: хранит список книг как массив строк и печатает его на экран.

import Foundation

let readingList = [
    "The Left Hand of Darkness",
    "The Hobbit",
    "Foundation"
]

print("Мой список чтения:")      // Мой список чтения:
print(readingList)               // ["The Left Hand of Darkness", "The Hobbit", "Foundation"]

Здесь import Foundation не обязателен для массивов, но в консольных проектах его часто оставляют «по привычке»: дальше обычно идут строки, ввод, форматирование и прочие удобства. Если хотите, можете убрать — пример всё равно скомпилируется.

Массивы разных типов: [Int], [String], [Bool]

Когда вы только начинаете, может казаться, что тип элементов — это «формальность». Но для Swift это фундамент. Тип определяет, какие операции доступны и что вообще считается корректным.

Например, массив чисел можно использовать для статистики, а массив строк — для вывода сообщений и обработки текста. Swift не позволит вам случайно сложить строку с числом «внутри массива» без явного преобразования — и это экономит часы жизни (обычно те, которые вы бы потратили на поиск глупого бага в 2 ночи).

let attempts: [Int] = [1, 2, 3, 4]
let names: [String] = ["Ana", "Ben"]
let isCompleted: [Bool] = [true, false, false]

print(attempts)      // [1, 2, 3, 4]
print(names)         // ["Ana", "Ben"]
print(isCompleted)   // [true, false, false]

Массив массивов

Частый вопрос: «Можно ли сделать массив, где элементы — тоже массивы?» Технически да: тип будет выглядеть как [[Int]] или [[String]].

Пока без индексов и без «матриц» — просто одна строчка, чтобы идея не выглядела магией:

let shelves: [[String]] = [["A", "B"], ["C"]]
print(shelves) // [["A", "B"], ["C"]]

Запомните сейчас главное: если элемент массива — это другой массив, тип становится «двойными скобками».

Печать массива через print() как инструмент отладки

На старте программирования важно иметь «фонарик», которым вы подсвечиваете то, что реально происходит в программе. print() — это ваш фонарик. И с массивами он работает удобно: Swift печатает массив в читаемом виде, с квадратными скобками и элементами через запятую.

Посмотрим, как это помогает видеть порядок:

let queue = ["first", "second", "third"]
print(queue) // ["first", "second", "third"]

Даже без индексов уже видно: порядок сохранён. Это пригодится позже, когда вы начнёте добавлять и удалять элементы, и print(queue) быстро покажет, «куда уехало» содержимое.

4. Ещё несколько полезных нюансов

Иногда массив создаётся не только литералом. Но пока держимся простых и читаемых вариантов, без забегания в новые темы.

Создать пустой массив и тут же распечатать:

var notes: [String] = []
print(notes) // []

Создать массив из одного элемента (да, это нормально):

let single = ["only one"]
print(single) // ["only one"]

Создать массив и дать ему «говорящее» имя — это не синтаксис, но важная привычка:

let errorMessages = ["Invalid input", "Try again"]
print(errorMessages) // ["Invalid input", "Try again"]

Таблица-шпаргалка по созданию массивов

Иногда полезно увидеть всё в одном месте, особенно если вы только привыкаете к синтаксису. Ниже маленькая шпаргалка именно по созданию, без индексов и мутаций.

Что хотим сделать Как пишем Комментарий
Создать массив чисел
let a = [1, 2, 3]
Тип [Int] выведется автоматически
Создать массив строк
let s = ["a", "b"]
Тип [String] выведется автоматически
Создать пустой массив строк
let x: [String] = []
Без типа [] непонятен
Создать пустой массив Int
var ids = [Int]()
Удобно, если будете добавлять позже
Указать тип через Array<T>
let a: Array<Int> = [1]
Эквивалент [Int], просто другая запись

5. Типичные ошибки при создании массивов

Ошибка №1: писать let a = [] и ждать, что Swift догадается о типе.
[] — это «ничего», и из этого невозможно вывести, что вы планировали хранить: строки, числа или, возможно, названия котиков. Исправление простое: либо укажите тип слева (let a: [Int] = []), либо создайте через конструктор (let a = [Int]()).

Ошибка №2: пытаться смешивать типы элементов в одном массиве.
Очень частый случай — «хочу [1, 2, 2.5]». Для человека это «числа», а для Swift — Int и Double, то есть разные типы. Правильный путь: решить, какой тип нужен (часто Double) и явно привести элементы: [1.0, 2.0, 2.5] или Double(1).

Ошибка №3: путать массив и кортеж из-за скобок.
[1, 2, 3] — массив, (1, 2, 3) — кортеж. У массива элементы одного типа и их можно хранить сколько угодно. У кортежа фиксированное число элементов, и типы могут быть разными. Если вы случайно написали круглые скобки, код либо не скомпилируется там, где вы ждёте массив, либо поведёт себя «не так».

Ошибка №4: объявить массив через let, а потом ожидать, что он будет расширяться.
Даже если вам «логически» хочется сказать: «само имя списка не меняется», но элементы будут добавляться, — это всё равно означает мутацию массива. Для изменений состава нужен var. Мы подробно будем менять массивы в следующих лекциях, но привычку «подумать про let/var заранее» стоит формировать уже сейчас.

Ошибка №5: давать массиву неинформативное имя и потом путаться, что внутри.
let a = ["Tom", "Ben"] компилируется, но через неделю вы забудете, что это: авторы, пользователи, теги? Хорошие имена (authors, usernames, tags) помогают читать код как текст — и это особенно важно, когда массивы начнут путешествовать по функциям и условиям.

1
Задача
Swift SELF, 11 уровень, 1 лекция
Недоступна
План на день
План на день
1
Задача
Swift SELF, 11 уровень, 1 лекция
Недоступна
Три контейнера
Три контейнера
1
Задача
Swift SELF, 11 уровень, 1 лекция
Недоступна
Датчик измерений
Датчик измерений
1
Задача
Swift SELF, 11 уровень, 1 лекция
Недоступна
Версии тегов
Версии тегов
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ