ako*_*e01 5 lua hashtable lua-table
我想存储一个lua表,其中键是其他lua表.我知道这是可能的但我希望能够使用这些表的副本在表中查找.具体来说,我希望能够做到:
t = {}
key = { a = "a" }
t[key] = 4
key2 = { a = "a" }
Run Code Online (Sandbox Code Playgroud)
然后我希望能够查找:
t[key2]
Run Code Online (Sandbox Code Playgroud)
得到4.
我知道我可以key变成一个字符串并将其放入表格中t.我还考虑过编写自定义哈希函数或者通过嵌套表来实现这一点.有没有最好的方法让我获得这种功能?我还有其他选择吗?
在Lua中,分别创建的两个表被认为是"不同的".但是如果你创建一个表,你可以将它分配给你想要的任何变量,当你比较它们时,Lua会告诉你它们是平等的.换一种说法:
t = {}
key = { a = "a" }
t[key] = 4
key2 = key
...
t[key2] -- returns 4
Run Code Online (Sandbox Code Playgroud)
所以,这就是做你想做的简单,干净的方式.存储在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
Run Code Online (Sandbox Code Playgroud)
该函数必须是递归的,以处理包含表本身的表.如果其中一个表"包含"另一个表但具有更多元素,也不能被愚弄.我出来了这个实现; 可能那里有更好的.
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
Run Code Online (Sandbox Code Playgroud)
我不打算在这里解释这个功能.我希望它能够清楚地表明它的作用.
该难题的另一部分在于比较键时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
})
Run Code Online (Sandbox Code Playgroud)
用法示例:
t[{a = 1}] = 4
print(t[{a = 1}]) -- 4
print(t[{a = 1, b = 2}]) -- nil
Run Code Online (Sandbox Code Playgroud)