一、Lua table拷贝功能分析
在lua的table中,并没有像其它语言那样为类提供拷贝函数,所以需要开发者额外实现;
没有统一的实现的主要原因,在于table的复杂性,table可以包含各种类型的值,以及包含元表等,统一的实现并不能满足我们实际遇到的各种需求;
二、几种常见需求的实现
1.数组table的拷贝
数组table的拷贝比较简单,但是要求要拷贝的table中不能包含散列表数据,否则会丢失散列表数据;(但是这也是一种提取数组索引的数据的一种方法,就是通过unpack拿到所有的数组索引数据,然后使用{}包装起来)
function table.clone(tb)
return {table.unpack(tb)}
end
local tb = {3, 1, 5}
local cloneTb = table.clone(tb)
table.sort(tb)
print(tb[1], cloneTb[2])
2.浅拷贝,拷贝表的最顶层数据
最简单的浅拷贝,是扩充了数组table的拷贝,使其可以拷贝一个任意table的数据,但是只拷贝直接索引到的数据;而且不关心元表等数据;
注意:浅拷贝虽然也能拷贝到所有的数据,但是它浅拷贝的部分的数据是和其它数据共享一个table对象的,这也是称其为浅拷贝的原因;如下示例,只有最顶层的变量的数据是在新的table中的;
function table.shallowCopy(tb)
local copy = {}
for k, v in pairs(tb) do
copy[k] = v
end
return copy
end
local tb = {x="hello", y="world" , z={name = "tb"}}
local copyTb = table.shallowCopy(tb)
print(copyTb.x) -- hello
print(copyTb.z.name) -- tb
tb.z.name = "newTb"
tb.x = "newHello"
print(copyTb.x) -- hello
print(copyTb.z.name) -- newTb
3.深拷贝,递归拷贝所有数据到新表中
如下,一个递归的深拷贝,包含了元表的深拷贝;
function table.deepCopy(tb)
if tb == nil then
return nil -- 参见注1
end
local copy = {}
for k, v in pairs(tb) do
if type(v) == 'table' then
copy[k] = table.deepCopy(v)
else
copy[k] = v
end
end
-- local meta = table.deepCopy(getmetatable(tb))
setmetatable(copy, table.deepCopy(getmetatable(tb)))
return copy
end
local tb = {x="hello", y="world" , z={name = "tb"}}
local copyTb = table.deepCopy(tb)
print(copyTb.x) -- hello
print(copyTb.z.name) -- tb
tb.z.name = "newTb"
tb.x = "newHello"
print(copyTb.x) -- hello
print(copyTb.z.name) -- tb
注1:在这里,如果是return而不是return nil,那么在setmetatable函数中会报错,第二个参数错误;因为在lua中nil也是一种变量类型,no return value和return nil是有区别的;
上述拷贝的实现没有考虑到key为一个table类型的情况: