Таблицы как словари

Используем таблицы для хранения данных по именованным ключам.

Словарь (ассоциативный массив) — это таблица, где значения хранятся не по номерам, а по именам-ключам.

Список хорош, когда важен порядок. Но часто нужно хранить данные по имени: здоровье игрока, его уровень, имя. Здесь таблица работает как словарь.

Создание словаря

local player = {
  name = "Алиса",
  hp = 100,
  level = 5
}
print(player.name)      -- доступ через точку
print(player["hp"])     -- доступ через скобки

Вывод:

Алиса
100

Два способа доступа эквивалентны: player.name — это сокращение для player["name"].

Когда нужны скобки

Точка работает, только если ключ — простое имя. Для ключей с пробелами, числами или из переменной нужны скобки:

local config = {}
config["max speed"] = 200    -- пробел в ключе
local key = "hp"
player[key] = 80             -- ключ из переменной
print(player.hp)

Вывод:

80

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

Чтобы добавить поле — просто присвойте ему значение. Чтобы удалить — присвойте nil:

player.gold = 50      -- добавили поле
player.level = nil    -- удалили поле
print(player.gold, player.level)

Вывод:

50	nil

Перебор словаря через pairs

ipairs для словаря не годится — там нет порядковых номеров. Используем pairs:

local scores = {alice = 10, bob = 7, eve = 15}
for name, score in pairs(scores) do
  print(name, score)
end

Вывод:

alice	10
bob	7
eve	15

Порядок перебора через pairs не гарантирован — Lua может выдать ключи в любом порядке.

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

Именованные ключи хранятся в хеш-части таблицы. Lua вычисляет хеш от ключа и кладёт значение в соответствующую ячейку. Поэтому доступ по ключу очень быстр, но порядок ключей теряется — отсюда непредсказуемость pairs.

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

  • Перебирать словарь через ipairs — он остановится сразу, ведь ключа 1 там нет.
  • Рассчитывать на порядок ключей в pairs. Если нужен порядок — храните ключи отдельным списком.
  • Считать, что # вернёт число пар в словаре. Он работает только со списочной частью.

Итог

  • Как словарь таблица хранит значения по именованным ключам.
  • Доступ через точку t.key или скобки t["key"]; скобки нужны для сложных ключей.
  • Удаление поля — присвоение ему nil.
  • pairs перебирает все пары ключ-значение, но порядок не гарантирован.
Проверьте себя
1. Чем pairs отличается от ipairs при переборе таблицы?
Apairs работает только с числами
Bpairs перебирает все ключи, включая строковые, но без гарантии порядка
Cipairs быстрее в десять раз
DОни полностью одинаковы
2. Как удалить поле из таблицы-словаря?
Atable.delete(t, key)
BПрисвоить ему nil: t.key = nil
CНельзя удалить
Dremove(t.key)
3. Что эквивалентно записи player.name?
Aplayer(name)
Bplayer->name
Cplayer["name"]
Dname.player