# Cloning Tables

Aug 29 2019, 9:27 AM PST 5 min

Sometimes it’s useful to be able to copy — or “clone” — a table. Lua provides no built in function to copy tables, so we must write our own.

## Shallow Copies

Doing a shallow copy involves looping over all the keys in one table using `pairs`, then assigning them to another table. We can create a simple function to do this.

``````local function shallowCopy(original)
local copy = {}
for key, value in pairs(original) do
copy[key] = value
end
return copy
end
``````

We’ll want a small function to print out tables to see what’s going on:

``````local function stringifyTable(t)
local entries = {}
for k, v in pairs(t) do
-- if we find a nested table, convert that recursively
if type(v) == **table** then
v = stringifyTable(v)
else
v = tostring(v)
end
k = tostring(k)

-- add another entry to our stringified table
entries[#entries + 1] = ("s = s"):format(k, v)
end

-- the memory location of the table
local id = tostring(t):sub(8)

return ("{s}@s"):format(table.concat(entries, **, **), id)
end
``````

This function doesn’t cover all situations well, and it’s not too important to understand how it works, but it shows us what we need to know:

``````local original = { key = "Value", pieIsTasty = false }
local reassigned = original
local copied = shallowCopy(original)

t.pieIsTasty = true

print("original", stringifyTable(original))
print("reassigned", stringifyTable(reassigned))
print("copied", stringifyTable(copied))
``````
###### Output:
``````original    {key = Value, pieIsTasty = true}@0025B560
reassigned  {key = Value, pieIsTasty = true}@0025B560
copied      {key = Value, pieIsTasty = false}@0025B420
``````

You can see from this output that `original` and `reassigned` have the same ID, so they refer to the same table. As a result, when one is changed, the other changes too. By copying `original` into `copied`, this change does not transfer.

### Arrays

Lua does most of the work for us when shallow-copying an array:

``````local original = {1, 3, 5, 7, 9}
local copy = {unpack(original)}
``````

## Deep Copies

Sometimes a shallow copy isn’t enough. Consider:

``````local original = { Shedletsky = { score=2 }, Builderman = { score = 1 } }
local snapshot = shallowCopy(original)  -- A snapshot of the scores as they were

original[**Shedletsky**].score = 5

print("original", stringifyTable(original))
print("snapshot", stringifyTable(snapshot))
``````
###### Output:
``````original  {Shedletsky: {score: 5}@0019B6F0, Builderman: {score: 1}@0019B5B0}@0019B470
snapshot  {Shedletsky: {score: 5}@0019B6F0, Builderman: {score: 1}@0019B5B0}@0019B600
``````

Oops! Looks like we accidentally updated the score in our snapshot — notice that while the outer tables have different IDs, the inner ones have the same IDs. We need to make copies there too. To do that, we should use recursion.

``````local function deepCopy(original)
local copy = {}
for k, v in pairs(original) do
-- as before, but if we find a table, make sure we copy that too
if type(v) == **table** then
v = deepCopy(v)
end
copy[k] = v
end
return copy
end
``````

Giving what we intended:

``````local original = { Shedletsky = { score = 2 }, Builderman = { score = 1 } }
local snapshot = deepCopy(original)  -- A snapshot of the scores as they were

original[**Shedletsky**].score = 5

print("original", stringifyTable(original))
print("snapshot", stringifyTable(snapshot))
``````
###### Output:
``````original  {Shedletsky: {score: 5}@0046B7E0, Builderman: {score: 1}@0046B1F0}@0046B3D0
snapshot  {Shedletsky: {score: 2}@0046B240, Builderman: {score: 1}@0046B560}@0046B510
``````

In some cases, it may be desirable to make `deepCopy()` copy keys which are tables as well as values. However, this should be done with caution, since table keys are looked up by ID, not value:

``````local range = {1, 2, 3, 4, 5}
local isUseful = { [range] = true }

local copiedRange = shallowCopy(range)

print(isUseful[range])
print(isUseful[copiedRange])
``````
###### Output:
``````true
nil
``````
Tags:
• cloning
• tables