Задать вопрос

Как правильно удалять элементы массива в LUA?

хочу добавить в свою игру объекты которые были бы не заранее прописаны в level.load, а могли бы создаваться и удаляться напрямую или косвенно действиями игрока. Добавлять их думаю можно так: object[#object+1]=... но как правильно удалить такой объект? Ведь если просто object[i] = nil то в какой-то момент длинна массива может стать очень большой и думаю это может вызвать проблемы
  • Вопрос задан
  • 1613 просмотров
Подписаться 1 Средний Комментировать
Решения вопроса 1
dollar
@dollar Куратор тега Lua
Делай добро и бросай его в воду.
Вместо object[#object+1]=x лучше писать table.insert(object, x)
Это так, к слову.

А удалять со сдвигом можно через remove:
table.remove(object, i)
Это приведёт к удалению элемента с индексом i, а также к смещению всех последующих элементов на 1 влево, чтобы в таблице в итоге не было дырки.

Считается, что это не самый оптимальный способ работы с массивами. Но так как это встроенная функция, и сам Lua написан на C, то получается довольно быстро в пределах нескольких сотен элементов.

С учётом того, что игровые объекты у вас будут появляться/удаляться не каждый тик, а очень редко, такой способ вполне хорош.

=============================================

В зависимости от задачи, можно по-разному оптимизировать её решение.

Если важен быстрый поиск (по ключу), то лучше использовать уникальный ключ вместо ничего не значащего порядкового номера.
object[x.id] = x

Перебор всех объектов будет возможен через pairs. Правда, без гарантии того, в каком порядке будет перебор:
for k,v in pairs(object) do

Если при этом нужно где-то считать количество всех объектов, то это можно делать в отдельной переменной. При таком подходе можно даже в случае безликих индексов наращивать их до бесконечности, не парясь о дырках, а перебор через pairs. В любом случае подсчёт количества - не проблема. Есть два варианта, как можно это делать:
а) Если количество нужно редко, а добавление/удаление происходит часто, то считать можно каждый раз заново:
local cnt = 0
for _ in pairs(object) do
  cnt = cnt + 1
end

б) Если же количество нужно считать часто, а добавление/удаление объектов происходит редко, то лучше обновлять счетчик при добавлении и удалении:
objects_cnt = 0 --всегда содержит количество объектов

--добавление
object[x.id] = x;
objects_cnt = objects_cnt + 1;

 --удаление
object[x.id] = nil;
objects_cnt = objects_cnt - 1;
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы