Lua 复制并拆分 table
Lua copy and split table
我有一个大table,其中包含大量递归子table:
table1={p1={def={...}},
p2={...},
p3={...},
...
p(n)={...}
}
我需要一份 table 的副本,其中仅包含某些子 tables
plist={"p1", "p3", "p10",...}
因此,我应该得到一个 table 的形式:
table2={p1={def={...}},
p3={...},
p10={...},
...
}
table1 应该保持不变。
我尝试使用此代码:
function deepcopy(o, seen)
seen = seen or {}
if o == nil then return nil end
if seen[o] then return seen[o] end
local no
if type(o) == 'table' then
no = {}
seen[o] = no
for k, v in next, o, nil do
no[deepcopy(k, seen)] = deepcopy(v, seen)
end
setmetatable(no, deepcopy(getmetatable(o), seen))
else
no = o
end
return o
end
local table2 = deepcopy(plist, table1)
还有这个:
local 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
local table2 = copy(plist, table1)
两个给我都不对table2。我应该使用什么代码?
我认为这里最好的策略是先过滤然后执行深拷贝,因为很难在执行深拷贝的同时正确地仅过滤顶层。
function filter(tb, fields)
local ret = {}
for i, field in ipairs(fields) do
ret[field] = tb[field]
end
return ret
end
-- Taken from luno library: https://github.com/echiesse/luno/blob/master/src/util.lua
function copy(val, lookup)
local ret
lookup = lookup or {}
if type(val) == "table" then
if lookup[val] ~= nil then
ret = lookup[val]
else
ret = {}
lookup[val] = ret
for i, v in pairs(val) do
local index = lookup[i] or copy(i, lookup)
local value = lookup[v] or copy(v, lookup)
ret[index] = value
end
end
else
ret = val
end
return ret
end
function filterAndCopy(tb, fields, lookup)
local temp = filter(tb, fields)
return copy(temp)
end
你可以这样测试:
a = {a=1, b=2}
b = filterAndCopy(a, {"b"})
for k, v in pairs(b) do
print(k, v)
end
产生输出:
b 2
我有一个大table,其中包含大量递归子table:
table1={p1={def={...}},
p2={...},
p3={...},
...
p(n)={...}
}
我需要一份 table 的副本,其中仅包含某些子 tables
plist={"p1", "p3", "p10",...}
因此,我应该得到一个 table 的形式:
table2={p1={def={...}},
p3={...},
p10={...},
...
}
table1 应该保持不变。
我尝试使用此代码:
function deepcopy(o, seen)
seen = seen or {}
if o == nil then return nil end
if seen[o] then return seen[o] end
local no
if type(o) == 'table' then
no = {}
seen[o] = no
for k, v in next, o, nil do
no[deepcopy(k, seen)] = deepcopy(v, seen)
end
setmetatable(no, deepcopy(getmetatable(o), seen))
else
no = o
end
return o
end
local table2 = deepcopy(plist, table1)
还有这个:
local 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
local table2 = copy(plist, table1)
两个给我都不对table2。我应该使用什么代码?
我认为这里最好的策略是先过滤然后执行深拷贝,因为很难在执行深拷贝的同时正确地仅过滤顶层。
function filter(tb, fields)
local ret = {}
for i, field in ipairs(fields) do
ret[field] = tb[field]
end
return ret
end
-- Taken from luno library: https://github.com/echiesse/luno/blob/master/src/util.lua
function copy(val, lookup)
local ret
lookup = lookup or {}
if type(val) == "table" then
if lookup[val] ~= nil then
ret = lookup[val]
else
ret = {}
lookup[val] = ret
for i, v in pairs(val) do
local index = lookup[i] or copy(i, lookup)
local value = lookup[v] or copy(v, lookup)
ret[index] = value
end
end
else
ret = val
end
return ret
end
function filterAndCopy(tb, fields, lookup)
local temp = filter(tb, fields)
return copy(temp)
end
你可以这样测试:
a = {a=1, b=2}
b = filterAndCopy(a, {"b"})
for k, v in pairs(b) do
print(k, v)
end
产生输出:
b 2