Таблицы как массивы

Знакомимся с таблицами — единственной структурой данных Lua — в роли списков.

Таблица — универсальный контейнер Lua, который умеет быть и списком, и словарём, и объектом одновременно.

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

Создание списка

local fruits = {"яблоко", "банан", "вишня"}
print(fruits[1])   -- первый элемент
print(fruits[2])
print(#fruits)     -- сколько элементов

Вывод:

яблоко
банан
3

Снова видим главную особенность Lua: индексы начинаются с единицы. Первый элемент — это fruits[1], а не fruits[0].

Добавление и удаление

Для работы со списками есть библиотека table:

local nums = {10, 20, 30}
table.insert(nums, 40)        -- добавить в конец
table.insert(nums, 1, 5)      -- вставить в начало
table.remove(nums, 2)         -- удалить второй элемент
print(nums[1], nums[2], nums[3], nums[4])

Вывод:

5	20	30	40

Перебор списка

Перебрать все элементы по порядку проще всего через ipairs:

local heroes = {"маг", "воин", "лучник"}
for i, hero in ipairs(heroes) do
  print(i, hero)
end

Вывод:

1	маг
2	воин
3	лучник

Схема таблицы-массива

fruits = {
  [1] = "яблоко",   <-- ключ 1
  [2] = "банан",    <-- ключ 2
  [3] = "вишня"     <-- ключ 3
}
#fruits == 3

Как работает под капотом

Внутри таблица состоит из двух частей: массивной (для подряд идущих целых ключей 1, 2, 3...) и хеш-части (для всего остального). Когда ключи — это 1, 2, 3 без дыр, Lua хранит их в массивной части, и доступ становится очень быстрым. Поэтому списки в Lua эффективны.

Частые ошибки

  • Начинать список с индекса 0. Оператор # и ipairs ожидают ключи с единицы.
  • Оставлять «дыру» в списке (например, ключи 1, 2, 4). Тогда # может вернуть неожиданное значение.
  • Удалять элементы во время перебора через ipairs — это сбивает индексы.

Итог

  • Таблица — единственная структура данных Lua; как список она хранит элементы по индексам с единицы.
  • Библиотека table даёт insert и remove для изменения списка.
  • ipairs перебирает элементы по порядку, давая индекс и значение.
  • Подряд идущие целые ключи Lua хранит в быстрой массивной части.
Проверьте себя
1. Какой индекс у первого элемента таблицы-массива в Lua?
A0
B1
C-1
Dлюбой
2. Что делает table.insert(nums, 40)?
AУдаляет элемент 40
BДобавляет 40 в конец таблицы
CСтавит 40 на первую позицию
DЗаменяет всю таблицу на 40