Last active
August 24, 2017 16:49
-
-
Save cpeosphoros/0aa286c6b39c1e452d9aa15d7537ac95 to your computer and use it in GitHub Desktop.
Lua Deepcopy with table recursion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function deepCopy(value, cache, promises, copies) | |
cache = cache or {} | |
promises = promises or {} | |
copies = copies or {} | |
local copy | |
if type(value) == 'table' then | |
if(cache[value]) then | |
copy = cache[value] | |
else | |
promises[value] = promises[value] or {} | |
copy = {} | |
for k, v in next, value, nil do | |
local nKey = promises[k] or deepCopy(k, cache, promises, copies) | |
local nValue = promises[v] or deepCopy(v, cache, promises, copies) | |
copies[nKey] = type(k) == "table" and k or nil | |
copies[nValue] = type(v) == "table" and v or nil | |
copy[nKey] = nValue | |
end | |
local mt = getmetatable(value) | |
if mt then | |
setmetatable(copy, mt.__immutable and mt or deepCopy(mt, cache, promises, copies)) | |
end | |
cache[value] = copy | |
end | |
else -- number, string, boolean, etc | |
copy = value | |
end | |
for k, v in pairs(copies) do | |
if k == cache[v] then | |
copies[k] = nil | |
end | |
end | |
local function correctRec(tbl) | |
if type(tbl) ~= "table" then return tbl end | |
if copies[tbl] and cache[copies[tbl]] then | |
return cache[copies[tbl]] | |
end | |
local new = {} | |
for k, v in pairs(tbl) do | |
local oldK = k | |
k, v = correctRec(k), correctRec(v) | |
if k ~= oldK then | |
tbl[oldK] = nil | |
new[k] = v | |
else | |
tbl[k] = v | |
end | |
end | |
for k, v in pairs(new) do | |
tbl[k] = v | |
end | |
return tbl | |
end | |
correctRec(copy) | |
return copy | |
end | |
return deepCopy |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment