I need to interact with an array and delete some elements.
But it seems table.remove shifts the Id and it’s messing the for / ipairs loop:
local arr = {}
for i = 1, 10, 1 do -- will create arr{"value1" ... "value10"}
table.insert(arr, "value" .. i)
end
for i, v in ipairs(arr) do
print(i, v)
table.remove(arr, i)
end
This will print:
1 value1
2 value3
3 value5
4 value7
5 value9
and the array will remain with:
"value2", "value4", "value6", "value8", "value10"
What’s the correct way to interact with an array and remove items inside a loop?
It’s generally not a good idea to use table.remove while iterating through an array’s elements, since the function shifts the positions of other elements to fill in the gap.
One way to work around it could be to record the elements to be removed, and remove afterwards in a second iteration.
local arr = {}
for i = 1, 10, 1 do -- will create arr{"value1" ... "value10"}
table.insert(arr, "value" .. i)
end
local toBeRemoved = {}
for i, v in ipairs(arr) do
print(i, v)
table.insert(toBeRemoved, i)
end
-- start from the highest indexes so the shifting won't affect the placement of the next elements
table.sort(toBeRemoved)
for i = #toBeRemoved, 1, -1 do
table.remove(arr, toBeRemoved[i])
end
I found a better way of doing it, you basically account for the number of removed entries so you can accurately find the correct index:
local arr = {}
for i = 1, 10, 1 do -- will create arr{"value1" ... "value10"}
table.insert(arr, "value" .. i)
end
local removedEntries = 0
for i = 1, #arr do
table.remove(arr, i - removedEntries)
removedEntries = removedEntries + 1
end
--testing if the array is empty:
print(next(arr)) --will print nil
In this case, i - removedEntries will be always 1.
But this led me to understand how table.remove works inside a loop: once it shifts the table, for each remove for an item with Id 1, the item with Id 2 becomes 1, Id 3 becomes 2 and so on…
Thus, the simplest solution would always be to remove Id 1 (not the for Id variable):
for i = 1, #arr do
table.remove(arr, 1) -- Id 2 becomes 1, 3 becomes 2, ...
end