vettim89 wrote: Mon May 09, 2022 12:04 am
Of course! That makes perfect sense now that your point it out. Can you make a 'for' loop counter backwards?
Perhaps I need to use a do/while loop instead
No you should not use a do\while.
You can use a decrementing for if you want and it will technically address your specific issue in this specific case, however it may not work for you in other cases. How to go backwards: for i=#sometable,1,-1 do print(i); end
The issue is you are indirectly making deletes to the object being looped during the loop which changes things on each iteration. Don't if you can avoid it. Often you will want to either deep-copy the table first, or run through it grabbing what you need first, and then a second time to do the actions.
--using decrementing for loop which will technically work for this very specific example.
Code: Select all
function DeleteAllHostedUnits1(u)
if ((u ~= nil) and u.hostedUnits ~=nil) and u.hostedUnits.Aircraft ~=nil then
local tmptable = u.hostedUnits.Aircraft -- make a copy as the original may be reevaluated\updates during the for.
for i=#u.hostedUnits.Aircraft,1,-1 do
--There is no need to get each unit, unless doing something else first, line removed.
print('deleting unit ' .. i .. ' with guid ' .. u.hostedUnits.Aircraft[i] .. ' that was hosted on ' .. u.name)
pcall(ScenEdit_DeleteUnit,{guid=u.hostedUnits.Aircraft[i]});
end
end
end
DeleteAllHostedUnits1(ScenEdit_GetUnit({name='SUA1', guid='4FH7PU-0HMHHATCAVSIG'}));
--using simple copy by value first.
Code: Select all
function DeleteAllHostedUnits2(u)
if ((u ~= nil) and u.hostedUnits ~=nil) and u.hostedUnits.Aircraft ~=nil then
local tmptable = {};
for i = 1,#u.hostedUnits.Aircraft do tmptable[i]=u.hostedUnits.Aircraft[i]; end -- made clean copy of just the values we need
for k,v in ipairs(tmptable) do --operate on the copy you could not use idx or pairs here it doesn't matter just a sample.
pcall(ScenEdit_DeleteUnit,{guid=v});
print('deleted unit ' .. k .. ' with guid ' .. v .. ' that was hosted on ' .. u.name)
end
end
end
DeleteAllHostedUnits2(ScenEdit_GetUnit({name='SUA1', guid='4FH7PU-0HMHHATCAVSIG'}));
Using a deep-copy for more involved tables\objects, ie values that are tables themselves. (duplicate by-value not reference whole structure)
Code: Select all
local gKH={} --added just so I didn't have to change anything for this posted snippet.
gKH.base = {}; --added just so I didn't have to change anything for this posted snippet.
---Function to make a true copy an existing table into a real new table that has no references to old table.
-- Rarely needed, but when you really do you do.
-- Used by RandomUnitGenerator during recursion to avoid some refference problems.
-- original code from:
-- https://stackoverflow.com/questions/640642/how-do-you-copy-a-lua-table-by-value
---@param o table @table to copy
---@param seen? table @table used during recursion
---@return table @an unreferenced copy of the table fed to it.
function gKH.base.deepcopy(o, seen)
seen = seen or {}
if o == nil then return nil end
if seen[o] then return seen[o] end
local no
if type(o) == 'table' then
no = {}
seen[o] = no
for k, v in next, o, nil do
no[gKH.base.deepcopy(k, seen)] = gKH.base.deepcopy(v, seen)
end
setmetatable(no, gKH.base.deepcopy(getmetatable(o), seen))
else -- number, string, boolean, etc
no = o
end
return no
end
--usage
function DeleteAllHostedUnits3(u)
if ((u ~= nil) and u.hostedUnits ~=nil) and u.hostedUnits.Aircraft ~=nil then
local tmptable = gKH.base.deepcopy(u.hostedUnits.Aircraft); --byvalue copy of entire table.
for k,v in ipairs(tmptable) do -- could use idx or pairs method this is just a quick sample.
pcall(ScenEdit_DeleteUnit,{guid=v});
print('deleted unit ' .. k .. ' with guid ' .. v .. ' that was hosted on ' .. u.name)
end
end
end
DeleteAllHostedUnits3(ScenEdit_GetUnit({name='SUA1', guid='4FH7PU-0HMHHATCAVSIG'}));