【发布时间】:2013-07-10 00:34:21
【问题描述】:
在 Lua 中,我可以使用 table.insert(tableName, XYZ) 在表中添加一个条目。有没有办法可以将已经存在的表添加到表中?我的意思是直接调用而不是遍历并添加它。
谢谢
【问题讨论】:
-
您是指通过引用还是按值添加现有表?如果按值计算,则意味着将内容从现有表复制到新表并插入。前者在添加时不需要任何遍历,因为没有进行复制。你是这个意思吗?
在 Lua 中,我可以使用 table.insert(tableName, XYZ) 在表中添加一个条目。有没有办法可以将已经存在的表添加到表中?我的意思是直接调用而不是遍历并添加它。
谢谢
【问题讨论】:
您示例中的插入将适用于 XYZ 变量(数字、字符串、表格、函数等)中的任何内容。
虽然它会插入实际的表,但它不会复制表。如果要插入表格的副本,则需要遍历它并插入内容。
【讨论】:
首先:通常,您确实不需要需要 table.insert 将新条目放入表中。 Lua 中的表是键值对的集合;可以这样输入:
local t = {} --the table
local key= "name"
local value = "Charlie"
t[key] = value --make a new entry (replace an existing value at the same key!)
print(t.name) --> "Charlie"
注意 key 可以有 any 类型(不仅仅是整数/字符串)!
通常您需要表来处理这种简单的特殊情况:值的序列(“列表”、“数组”)。对于 Lua,这意味着您需要一个表,其中所有键都是连续整数,并且包含所有非零值。 table.insert 函数适用于这种特殊情况:它允许您在某个位置插入一个值(或者如果没有指定位置,则将其附加到序列的末尾):
local t = {"a", "b", "d"} --a sequence containing three strings (t[1] = "a", ...)
table.insert(t, "e") --append "e" to the sequence
table.insert(t, 3, "c") --insert "c" at index 3 (moving values at higher indices)
--print the whole sequence
for i=1,#t do
print(t[i])
end
【讨论】:
如果我理解你的意思正确,你想这样做:
local t1 = {1, 2, 3}
local t2 = {4, 5, 6}
some_function(t1, t2)
-- t1 is now {1, 2, 3, 4, 5, 6}
如果不迭代t2,确实没有办法做到这一点。这是some_function的写法:
local some_function = function(t1, t2)
local n = #t1
for i=1,#t2 do t1[n+i] = t2[i] end
end
【讨论】:
不,您必须将第二个表的键/值对复制到第一个表中。从第二个表中复制现有值就是所谓的“浅拷贝”。第一个表将引用与第二个表相同的对象。
这在有限的情况下有效:
local n = #t1
for i=1,#t2 do t1[n+i] = t2[i] end
它确实尝试将t2 元素移动到现有t1 元素之外。这可能是一项至关重要的要求,但未在问题中说明。
不过也有一些问题:
#t1 和#t2,它会丢失非正整数的键,并且可能会丢失大于跳过的整数键的整数键(即从未分配或分配nil)。 __newindex 元方法。当只需要复制时,可能是不可取的。__index 元方法。当只需要复制时,这是不可取的。您可能认为如果只需要正整数键,则可以使用 ipairs,但它会在找到第一个 nil 值时退出,因此可能比 #t2 丢失更多。
改用pairs:
for key, value in pairs(t2) do
rawset( t1, key, value )
end
如果您确实希望避免在键匹配时替换现有的 t1 值,或者以某种方式映射 t2 键,则必须在需求中进行定义。
底线:pairs 是获取所有密钥的方法。它有效地执行rawget,因此它避免调用__index。 rawset 是在不调用 __newindex 的情况下进行复制的方式。
【讨论】:
nil 除外,在这种情况下,键被删除),包括表。因此,当复制一个值时,它是对复制的值的引用。如果该值引用一个内表,则副本将引用同一个内表。这与您对table.insert 所做的事情相同。如果没问题,那么你就完成了。如果您想要“深拷贝”而不是“浅拷贝”,请在问题和原因中说明。另请参阅here。