在Lua中,两个单独创建的表被视为“不同”。但是如果您创建一个表格一次,可以将其分配给任何想要的变量,并且当您比较它们时,Lua将告诉您它们相等。换句话说:
t = {}
key = { a = "a" }
t[key] = 4
key2 = key
...
t[key2]
那么,这就是做你想要的事情的简单清晰的方法。将key
存储在某个地方,以便您可以使用它检索4
。这也非常快速。
如果您真的不想这样做...好吧,有一种方法。但它有点低效和丑陋。
第一部分是创建一个比较两个不同表格的函数。如果两个表格是“相等”的,则它应该返回true,如果它们不是,则应该返回false。让我们称之为equivalent。它应该像这样工作:
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)
...
end
local store = {}
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