90

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?

2
  • 2
    There 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?... Commented Aug 16, 2009 at 3:30
  • i don't need any sort of comparison but i will be needing subtables...
    – RCIX
    Commented Aug 16, 2009 at 6:17

10 Answers 10

128
for k,v in pairs(second_table) do first_table[k] = v end
6
  • wait, does that catch string keys and such?
    – RCIX
    Commented Aug 16, 2009 at 3:30
  • 1
    This should work with some tweaking for handling subtables. Thanks!
    – RCIX
    Commented Aug 16, 2009 at 6:17
  • 32
    Doesn't this overwrite what is currently in the table if the indices are the same, as would be in an array? If you had two tables with number keys [1],[2],[3] etc., one with data already in and you merely iterate over the second table's keys, also [1],[2],[3] etc. and add the data in the same positions with the same keys to table one, you'll overwrite whatever was originally there. You could solve this with first_table[#first_table + k] = v. Personally I'd go about this using tables.insert(), though not sure that was available in 2009!
    – Astridax
    Commented Feb 22, 2014 at 23:09
  • 2
    In 99% of the cases this will be the correct solution, but do keep in mind that in applications with tables that reference other tables, which is common in object-oriented patterns, you may need to do extra bookkeeping. For instance, if there's some reason why the given table might reference itself directly, you'd want to check for 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.
    – Aiken Drum
    Commented Dec 22, 2017 at 11:06
  • 4
    @Astridax that is what the questioner asks for.
    – Moberg
    Commented Jan 27, 2018 at 8:32
24

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
  • 6
    Note that it is usually a bad idea to mess with standard Lua "namespaces" (like table.*). Better to make your own. Commented Aug 16, 2009 at 7:37
  • 4
    "if not t1[k] then t1[k] = {} end" contains a subtle bug (find it!) Better write it as "t1[k] = t1[k] or {}". Also, what happens if t2[k] is a table but t1[k] exists but is not a table? Finally, "table1[k] = v" should be "t1[k] = v".
    – lhf
    Commented Aug 17, 2009 at 18:08
  • 1
    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 {}).
    – idbrii
    Commented Mar 1, 2022 at 6:46
14

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
  • 3
    Yes, but if you look at RCIX's original post, there was some different logic in there that was later simplified to two identical else statements. It should have been further simplified into what you have here.
    – BMitch
    Commented Sep 19, 2011 at 13:17
  • 4
    Can anyone explain why t1[k] or false is necessary here?
    – what the
    Commented Oct 5, 2021 at 23:31
8

For numeric-index table merging:

for k,v in pairs(secondTable) do table.insert(firstTable, v) end
1
  • 3
    Isn't this solution wrong (as 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)
    – user202729
    Commented Nov 15, 2021 at 7:28
5

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
  • 2
    My comment was meant as a sarcasm: if you escape the recursion because you fear/expect a stack overflow; and then don't check whether your task container overflows your memory, then it doesn't make much sense to escape recursion in the first place.
    – Irfy
    Commented Sep 4, 2013 at 12:46
  • 2
    @Irfy, "general" memory used for tables in Lua or similar structures in other languages is most often more abundant than call stack space. Of course one should consider which solution is appropriate for particular environment, not just blindly copy/paste one or another. Commented Sep 9, 2013 at 18:53
5

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
3

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 :)

2

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
  • Your method insert new v with auto-incremented number index, right? Commented Dec 16, 2022 at 12:14
  • As posted in a comment earlier on Jimmy liu's answer: "Isn't this solution wrong (as 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)" (by user202729) Commented Apr 18, 2023 at 3:08
1

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 }

-1
for k,v in pairs(t2) do t1[k] = v end

key for string solution

Not the answer you're looking for? Browse other questions tagged or ask your own question.