Прежде всего, если balls
таблица представляет собой массив типа таблицы, или вы хотите, чтобы перебрать часть массива только, вы лучше использовать или стандартную for i
петлю вместо этого. pairs
выполняет итерацию по всем индексам таблицы, включая нечисловые, такие как строковые ключи.
Не говоря уже о том, что pairs
(next
с помощью) также итерация в неопределенном порядке, в то время как ipairs
всегда будет итерацией предсказуемым образом от 1
до первого целого ключа отсутствует в таблице. Обратите внимание: если вы используете стандартный цикл for i
с оператором длины #t
, это может быть немного иным, если ваша таблица не является последовательной.
За исключением случаев, __len метаметод не задан, длина таблицы т определяется только если таблица представляет собой последовательность, то есть множество его положительных цифровых клавиш равно {1..N} для некоторых целое число n. В этом случае n - его длина.
Во-вторых, устанавливая числовые индексы массива типа таблицы будет оставить таблицу с отверстиями.
local t = {1, 2, 3}
t[2] = nil
-- t is {1, nil, 3}, not {1, 3} as one might expect.
Вам нужно будет использовать table.remove
если вы хотите сохранить последовательную согласованность вашей таблицы.
local t = {1, 2, 3}
table.remove(t, 2)
-- t is {1, 3}
Последнее, но не менее является менее очевидным и менее интуитивное изъян в своем подходе к удалению элементов.
local t = {2, 3, 5, 2, 1}
for i=1, #t do
if t[i] % 2 == 1 then -- If value is odd,
table.remove(t, i) -- remove it.
end
end
-- t is {2, 3, 2}, but that can't be right.
Вы удаляете элементы из массива, когда вы перебираете их вперед. Это неизбежно приведет к тому, что вы пропустите каждый элемент после удаленной, возможно, до точки, где вы перебираете внешний массив.
Если вы хотите удалить элементы из массива при его переходе по нему, вы должны сделать это назад. Если по какой-то причине вы не можете перебирать назад по массиву, вам нужно будет сохранить список индексов для последующего удаления и повторить их позади.
На этом этапе вы можете спросить: «Почему назад? «Проще говоря, это потому, что цикл не обновляет длину или не сохраняет итератор так же, как размер таблицы уменьшается, что приводит к пропуску. Если вы переходите назад, вы сохраняете структуру, в которой обрабатывается итерация. Длина не нуждается в обновлении, так как теперь она является стартовым значением, а не конечным. Итератору не нужно «удерживать» или удерживать от шага, так как перед ним всегда будет больше элементов, из-за этого идет в обратном направлении
local t = {2, 3, 5, 2, 1}
for i=#t, 1, -1 do -- Start at the end and go backwards.
if t[i] % 2 == 1 then
table.remove(t, i)
end
end
-- t is {2, 2}, as expected.
в заключение (ТЛ;. др версия)
- Использование
ipairs
вместо pairs
для массивов, если вы предпочитаете использовать итераторы vs. с for i
цикла.
- Используйте
table.remove
для сохранения последовательности массива.
- Используйте обратные
for i
петли при удалении элементов из массивов.
Лучший ответ, касающийся таблиц lua. Поздравления. Это очень помогает мне. – MarcVit