I need to merge two tables, with the contents of the second overwriting contents in the first if a given item is in both. I looked but the standard libraries don't seem to offer this. Where can I get such a function?
-
2There is no single way of doing this. Are you comparing the keys or the values in the table? Is it possible for the keys / values to be other tables?...Karl Voigtland– Karl Voigtland2009-08-16 03:30:57 +00:00Commented Aug 16, 2009 at 3:30
-
i don't need any sort of comparison but i will be needing subtables...RCIX– RCIX2009-08-16 06:17:17 +00:00Commented Aug 16, 2009 at 6:17
10 Answers
for k,v in pairs(second_table) do first_table[k] = v end
6 Comments
v==second_table and, if so, assign first_table instead. Tables can also reference themselves indirectly, but that's probably a book's worth of problems to solve. I just wanted to put this on the radar, so 'nuff said.Here's what i came up with based on Doug Currie's answer:
function tableMerge(t1, t2)
for k,v in pairs(t2) do
if type(v) == "table" then
if type(t1[k] or false) == "table" then
tableMerge(t1[k] or {}, t2[k] or {})
else
t1[k] = v
end
else
t1[k] = v
end
end
return t1
end
3 Comments
tableMerge(t1[k] or {}, t2[k] or {}) would merge t2 into a new table and then discard that table. Maybe should be t1[k] = tableMerge(t1[k] or {}, t2[k] or {}).Wouldn't this work properly?
function merge(t1, t2)
for k, v in pairs(t2) do
if (type(v) == "table") and (type(t1[k] or false) == "table") then
merge(t1[k], t2[k])
else
t1[k] = v
end
end
return t1
end
2 Comments
For numeric-index table merging:
for k,v in pairs(secondTable) do table.insert(firstTable, v) end
1 Comment
pairs is not guaranteed to return elements in numeric order)? Besides table.insert is inefficient, see stackoverflow.com/a/15278426/5267751 (also see for other answers)Here's iterative version for deep merge because I don't like potential stack overflows of recursive.
local merge_task = {}
function merge_to_left_o(orig, new)
merge_task[orig] = new
local left = orig
while left ~= nil do
local right = merge_task[left]
for new_key, new_val in pairs(right) do
local old_val = left[new_key]
if old_val == nil then
left[new_key] = new_val
else
local old_type = type(old_val)
local new_type = type(new_val)
if (old_type == "table" and new_type == "table") then
merge_task[old_val] = new_val
else
left[new_key] = new_val
end
end
end
merge_task[left] = nil
left = next(merge_task)
end
end
2 Comments
Doug Currie's answer is the simplest for most cases. If you need more robust merging of tables, consider using the merge() method from the Penlight library.
require 'pl'
pretty.dump(tablex.merge({a=1,b=2}, {c=3,d=4}, true))
-- {
-- a = 1,
-- d = 4,
-- c = 3,
-- b = 2
-- }
2 Comments
true for a union, false for an intersection. github.com/stevedonovan/Penlight/blob/master/lua/pl/…I preferred James version for its simplicity and use it in my utils.lua - i did add a check for table type for error handling.
function merge(a, b)
if type(a) == 'table' and type(b) == 'table' then
for k,v in pairs(b) do if type(v)=='table' and type(a[k] or false)=='table' then merge(a[k],v) else a[k]=v end end
end
return a
end
Thanks for this nice function which should be part of the table class so you could call a:merge(b) but doing table.merge = function(a, b) ... did not work for me. Could even be compressed to a one liner for the real nerds :)
Comments
Like Doug Currie said, you can use his function, but there is a problem with his method. If first_table has things in it's k index, the function will over write it.
I'm assuming you're trying to merge these tables, not overwrite index's and value's. So this would be my method, it's very similar but is used for merging tables.
for _, v in pairs(second_table) do table.insert(first_table, v) end
The only problem with this solution is that the index is set as numbers, not as strings. This will work with tables with numbers as the index, and for tables with strings as their index, use Doug Currie's method.
Doug Currie's method:
for k,v in pairs(second_table) do first_table[k] = v end
2 Comments
v with auto-incremented number index, right?Extending this great answer, https://stackoverflow.com/a/1283399/1570165, I would like to go with a (pure) functional approach like this one below:
-- example values
local t1 = { a = 0, b = 2 }
local t2 = { a = 1, c = 3 }
-- merge function that takes functional approach
local merge = function(a, b)
local c = {}
for k,v in pairs(a) do c[k] = v end
for k,v in pairs(b) do c[k] = v end
return c
end
-- t1 and t2 value still same after merge
print(merge(t1, t2)) -- { a = 1, b = 2, c = 3 }
print(t2) -- { a = 1, c = 3 }
print(t1) -- { a = 0, b = 2 }