Lua 复制和分割表格

我有一个包含大量递归子表格的大表格:

table1={p1={def={...}},
        p2={...},
        p3={...},
        ...
        p(n)={...}
}

我需要得到一个仅包含某些子表格的副本

plist={"p1", "p3", "p10",...}

因此,我应该得到一个形如的表格:

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。我应该使用什么代码?

点赞
用户8273880
用户8273880

我认为这里的最佳策略是先过滤再执行深度复制,因为很难正确地仅对顶层进行过滤,同时仍然执行深度复制。

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
2017-12-01 15:50:14