Функции библиотеки table в Lua
Опубликовано:
- Добавление и удаление элементов —
table.insertиtable.remove - Объединение элементов в строку —
table.concat - Сортировка массивов —
table.sort - Распаковка и упаковка —
table.unpackиtable.pack - Копирование подмножества элементов —
table.move
table — одна из стандартных библиотек Lua, представляет собой модуль (набор функций) для управления индексированными таблицами (массивами), то есть ее функции почти не подходят для хэш-таблиц. Для последних операции выполняются стандартным синтаксисом языка.
Добавление и удаление элементов
Функции table.insert и table.remove используются для динамического изменения последовательностей. Данные операции можно считать одними из наиболее частых.
local inventory = {"Меч", "Щит"} -- table.insert(таблица, [позиция], значение) table.insert(inventory, "Зелье") -- Добавит в конец table.insert(inventory, 1, "Шлем") -- Вставит на 1-е место, остальное сдвинет print(table.concat(inventory, ", ")) -- table.remove(таблица, [позиция]) local removed = table.remove(inventory, 2) -- Удалит "Меч" и вернет его print("Удалено:", removed) print(table.concat(inventory, ", "))
Шлем, Меч, Щит, Зелье Удалено: Меч Шлем, Щит, Зелье
Быстрое объединение в строку
Функция table.concat — лучший способ быстро вывести содержимое списка (например, при формировании логов).
local words = {"one", "two", "three", "four"} -- Склеиваем элементы через пробел local sentence = table.concat(words, " ") print(sentence) -- Можно указать диапазон индексов local short = table.concat(words, " ", 3, 4) print(short)
one two three four three four
Следует использовать table.concat вместо соединения строк через .. в циклах, так как оно там не только медленное, но и расходует память. В примере ниже на каждой итерации цикла создается абсолютно новая строка в памяти, а старая выбрасывается. Если итераций много (например, сборка логов, генерация HTML или больших текстов), подобный код начнет тормозить программу и перегружать сборщик мусора (garbage collector).
local words = {'one', 'two', 'three', 'four', 'five', 'six', 'seven'} -- АНТИПРИМЕР: Склеивание через оператор '..' в цикле local result = '' for i = 1, #words do -- Нельзя изменить существующую строку 'result', -- поэтому каждый раз выделяется новая память под 'result .. words[i] + пробел' result = result .. words[i] .. '' end print(string.len(result)) -- 34
Сортировка массивов (списков, последовательностей)
Функция table.sort — это единственный стандартный способ отсортировать таблицу-массив в Lua. По умолчанию сортирует числа по возрастанию, а строки — по алфавиту. Для сложных структур нужно передавать свою функцию сравнения, то есть программист должен уметь писать кастомные функции сравнения (например, для сортировки объектов).
-- Простая сортировка local numbers = {5, 2, 9, 1} table.sort(numbers) print(table.concat(numbers, ", ")) -- Вывод: 1, 2, 5, 9 -- Сортировка сложных объектов (таблиц внутри таблицы) local players = { {name = "Alex", level = 50}, {name = "Elena", level = 85}, {name = "Ivan", level = 12} } -- Сортируем игроков по уровню (от большего к меньшему) table.sort(players, function(a, b) return a.level > b.level end) for _, player in ipairs(players) do print(player.name .. " (" .. player.level .. ")") end -- Вывод: -- Elena (85) -- Alex (50) -- Ivan (12)
Распаковка элементов таблиц и упаковка значений в таблицу
Функции table.unpack и table.pack полезны, когда нужно передать элементы таблицы как аргументы в функцию или, наоборот, собрать аргументы в таблицу.
-- table.unpack превращает массив в список аргументов local coordinates = {10, 20, 30} -- math.max(10, 20, 30) local max_val = math.max(table.unpack(coordinates)) print(max_val) -- Вывод: 30 -- table.pack собирает аргументы и автоматически добавляет поле "n" (количество элементов) -- Это критически важно, если среди аргументов может быть nil local my_pack = table.pack("A", nil, "C") print(my_pack.n) -- Вывод: 3 (хотя внутри есть nil)
Копирование подмножества элементов
Функция table.move появилась в Lua 5.3 и является одним из самых быстрых инструментов для копирования срезов. Она берет диапазон элементов из одной таблицы и вставляет их в другую (или в ту же самую) на указанную позицию.
Клонирование массива (или его части):
local source = {"яблоко", "банан", "груша", "слива"} local target = {} -- Копируем с 1 по 3 элемент из source в target, -- начиная с 1-й позиции target table.move(source, 1, 3, 1, target) print(table.concat(target, ", "))
яблоко, банан, груша
Слияние двух массивов путем добавления всех элементов одного массива в конец другого.
local inventory = {"Меч", "Щит"} local loot = {"Зелье", "Золото", "Руна"} -- Копируем весь loot в конец inventory -- Начинаем вставлять на позицию (#inventory + 1), то есть на индекс 3 table.move(loot, 1, #loot, #inventory + 1, inventory) print(table.concat(inventory, ", "))
Меч, Щит, Зелье, Золото, Руна
table.move умеет корректно перемещать элементы внутри одной и той же таблицы, даже если области копирования пересекаются. Это позволяет эффективно удалять элементы из середины массива без использования медленной table.remove. Допустим, мы хотим удалить 2-й элемент ("Б") из массива, сдвинув все элементы после него влево:
local alphabet = {"А", "Б", "В", "Г", "Д"} -- Сдвигаем элементы с 3 по 5 на одну позицию влево (начиная с индекса 2) table.move(alphabet, 3, 5, 2) -- Последний элемент продублировался, зануляем его вручную alphabet[5] = nil print(table.concat(alphabet, ", "))
А, В, Г, Д