Your iterator is getting mucked up because you're using pairs over a table whose indexes are changing inside the loop. As a rule, if you're iterating over a table with pairs or ipairs, you should try to avoid using table.remove and table.insert on that table inside the loop to avoid the sort of unpredictable behaviour you're seeing here.
Try this - it's definitely not optimized, but it should work:
lua Code:
local function tableMerge(...)
if select('#', ...) < 3 then error("tableMerge", "inputs") return end
local toReturn = {}
for i=1, select('#', ...) do
local tab = select(i, ...)
if type(tab) == "table" then --ignore any inputs which aren't tables
if not toReturn[1] then
for j,spellbar in pairs(tab) do -- do it this way so we don't actually do anything to the tables passed in
table.insert(toReturn, spellbar)
print("Adding " .. spellbar)
end
else
local n = #toReturn -- get the size of the array
-- iterate over the indices in the array
for j = 1,n do -- for everything that's common up to this point in iteration:
local v = toReturn[j] -- get the value at this index
print("Testing " .. v)
local found = false
for k,spellbar in pairs(tab) do -- for everything in this new table to check
if v == spellbar then -- if we found that the spellbar exists in this new table, say we found it
found = true
print("Found " .. spellbar)
end
end
if not found then -- if we didn't find this element, then remove it from the common table
print("Removing " .. toReturn[j])
toReturn[j] = nil -- set to nil to remove without changing the array
end
end
-- now we need to clean up the table
for j = 1,n do -- iterate over the array again
local v = toReturn[j] -- get the value at this index
if v then -- look for non-empty values
toReturn[j] = nil -- clear the current index
table.insert(toReturn, v) -- reinsert the value at the first non-empty index
end
end
end
end
end
return toReturn -- return everything that's common
end
And here's an alternative that may be quicker (only runs a cleanup function once) but won't preserve order, and might actually be slower (at least for a small number of tables) because it has to use pairs:
lua Code:
local function tableMerge(...)
if select('#', ...) < 3 then error("tableMerge", "inputs") return end
local toReturn = {}
local n -- define n outside the loop so we can use it later
for i=1, select('#', ...) do
local tab = select(i, ...)
if type(tab) == "table" then --ignore any inputs which aren't tables
if not toReturn[1] then
for j,spellbar in pairs(tab) do -- do it this way so we don't actually do anything to the tables passed in
table.insert(toReturn, spellbar)
print("Adding " .. spellbar)
end
n = #toReturn -- get the size of the initial table - it won't get any bigger than this
else
-- we have to iterate with pairs because after the first run, our table will have empty indices
for j, v in pairs(toReturn) do -- for everything that's common up to this point in iteration:
print("Testing " .. v)
local found = false
for k,spellbar in pairs(tab) do -- for everything in this new table to check
if v == spellbar then -- if we found that the spellbar exists in this new table, say we found it
found = true
print("Found " .. spellbar)
end
end
if not found then -- if we didn't find this element, then remove it from the common table
print("Removing " .. toReturn[j])
toReturn[j] = nil -- set to nil to remove without changing the array
end
end
-- note that the resulting table has a bunch of empty indices after each loop
end
end
end
-- now we can do a single cleanup run
for j = 1, n do -- iterate over the maximum size of the table
local v = toReturn[j] -- get the value at the current index
if v then -- if we have a non-nil value
toReturn[j] = nil -- remove the value from its current index
table.insert(toReturn, v) -- put the value in the first empty index
end
end
return toReturn -- return everything that's common
end
You'll want to check for typos, I haven't tested either code.