How do you copy a Lua table by value?

Table copy has many potential definitions. It depends on whether you want simple or deep copy, whether you want to copy, share or ignore metatables, etc. There is no single implementation that could satisfy everybody.

One approach is to simply create a new table and duplicate all key/value pairs:

function table.shallow_copy(t)
  local t2 = {}
  for k,v in pairs(t) do
    t2[k] = v
  end
  return t2
end

copy = table.shallow_copy(a)

Note that you should use pairs instead of ipairs, since ipairs only iterate over a subset of the table keys (ie. consecutive positive integer keys starting at one in increasing order).


Just to illustrate the point, my personal table.copy also pays attention to metatables:

function table.copy(t)
  local u = { }
  for k, v in pairs(t) do u[k] = v end
  return setmetatable(u, getmetatable(t))
end

There is no copy function sufficiently widely agreed upon to be called "standard".


To play a little readable-code-golf, here's a short version that handles the standard tricky cases:

  • tables as keys,
  • preserving metatables, and
  • recursive tables.

We can do this in 7 lines:

function copy(obj, seen)
  if type(obj) ~= 'table' then return obj end
  if seen and seen[obj] then return seen[obj] end
  local s = seen or {}
  local res = setmetatable({}, getmetatable(obj))
  s[obj] = res
  for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end
  return res
end

There is a short write-up of Lua deep-copy operations in this gist.

Another useful reference is this Lua-users wiki page, which includes an example on how to avoid the __pairs metamethod.