我想存储一个lua表,其中的键是其他lua表。我知道这是可能的,但是我希望能够使用这些表的副本在表中进行查找。具体来说,我希望能够做到:
t = {}
key = { a = "a" }
t[key] = 4
key2 = { a = "a" }
然后我希望能够查找:
t[key2]
并得到4。
我知道我可以将
key
转换为字符串并将其放入表t
中。我还考虑过编写自定义哈希函数或通过嵌套表来实现。我是否有最好的方法来获得这种功能?我还有什么其他选择?
最佳答案
在Lua中,分别创建的两个表被认为是“不同的”。但是,如果一次创建一个表,则可以将其分配给所需的任何变量,并且在比较它们时,Lua会告诉您它们相等。换句话说:
t = {}
key = { a = "a" }
t[key] = 4
key2 = key
...
t[key2] -- returns 4
因此,这就是做您想要的事情的简单,干净的方法。将
key
存储在某个地方,以便您可以使用它来取回4
。这也非常快。如果您真的不想这样做,那么...有一种方法。但这有点低效和丑陋。
第一部分是制作一个比较两个单独表的函数。如果两个表“相等”,则应返回true,否则返回false。我们称它为等效。它应该像这样工作:
equivalent({a=1},{a=1}) -- true
equivalent({a=1,b=2}, {a=1}) -- false
equivalent({a={b=1}}, {a={b=2}}) -- false
该函数必须是递归的,以处理包含表本身的表。如果其中一个表“包含”另一个表,但具有更多元素,则也不应欺骗它。我想到了这个实现。可能还有更好的选择。
local function equivalent(a,b)
if type(a) ~= 'table' then return a == b end
local counta, countb = 0, 0
for k,va in pairs(a) do
if not equivalent(va, b[k]) then return false end
counta = counta + 1
end
for _,_ in pairs(b) do countb = countb + 1 end
return counta == countb
end
我将不在这里解释该功能。我希望它已经足够清楚了。
难题的另一部分在于在比较键时使
t
使用equivalent
函数。这可以通过仔细的元表操作和一个额外的“存储”表来完成。我们基本上将
t
转换为冒名顶替者。当我们的代码告诉它在一个键下存储一个值时,它不会将其自身保存;而是将其提供给额外的表(我们将其称为store
)。当代码向t
询问值时,它将在store
中搜索它,但使用equivalent
函数来获取它。这是代码:
local function equivalent(a,b)
... -- same code as before
end
local store = {} -- this is the table that stores the values
t = setmetatable({}, {
__newindex = store,
__index = function(tbl, key)
for k,v in pairs(store) do
if equivalent(k,key) then return v end
end
end
})
用法示例:
t[{a = 1}] = 4
print(t[{a = 1}]) -- 4
print(t[{a = 1, b = 2}]) -- nil
关于lua - Lua:如何在键为表(或对象)的表中查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9201601/