将表格的内容用作关键词。
2011-5-26 13:55:2
收藏:0
阅读:137
评论:5
有没有一种简单的方法来创建类似于字典的集合,即:
- 表格可用作键
- 具有相同内容的表格被视为等效(而不是默认指针比较)
例如,在
t = createCustomTable()
k1 = {'a','b','c'}
k2 = {'a','b','c'}
t [k1] = true
t [k2]
应该计算为 true
。
此外,t
本身应该以相同的方式用作键。
是否有方法可以做到这一点,而不必
- 重新实现哈希表
- 将
k1
和k2
转换为字符串? (这是我目前正在做的。)
原文链接 https://stackoverflow.com/questions/6139684
点赞
stackoverflow用户597564
这个链接("Keys are references" 部分) 表示键是对象的引用,因此在您提供的示例中使用相同的表是行不通的。我认为您目前所做的方式可能是最好的方式,但我可能错了。
2011-05-26 14:42:44
stackoverflow用户206020
如果你可以接受一个依赖于库的话,你可以使用像Pentlight这样的东西,它似乎提供了setshttp://penlight.luaforge.net/#T10。
2011-05-26 20:03:24
stackoverflow用户107090
如果要将表作为键,并且其内容不会更改,您可以在 t
的 newindex
元方法中按需构建一个 SHA2 摘要,并将摘要用作实际键。该摘要将被缓存在另一个以真实表为索引的表中。
2011-05-26 22:33:02
stackoverflow用户34799
在《Lua 程序设计》第二版中,Lua 的首席架构师 Roberto Ierusalimschy 建议将这两个表序列化为字符串来进行内容索引。
如果你的所有关键表都是字符串数组(没有嵌入的空值),那么可以使用 table.concat(t,'\0')
快速完成此操作。(显然,如果你想要与索引无关的标识符,则需要对表进行 排序。)
2011-05-27 01:41:06
评论区的留言会收到邮件通知哦~
推荐文章
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
你可以在两个表的元表中实现并设置 __eq 方法。
k1 = {'a','b','c'} k2 = {'a','b','c'} mt1={__eq=function(a,b) for k,v in pairs(a) do if b[k]~=v then return false end end for k,v in pairs(b) do if a[k]~=v then return false end end return true end } setmetatable(k1,mt1) setmetatable(k2,mt1) assert(k1==k2,"Table comparison failed") function newDict(orig) if orig then return orig else local mt2={} local lookup ={} -- lookup table as upvalue to the metamethods mt2.__newindex = function(t,k,v) -- Registering a new table if type(k)~="table" then return end if v then -- v ~= false local found for idx,val in pairs(lookup) do if k==val then found=1 break end -- If already seen, skip. end if not found then lookup[#lookup+1]=k -- not seen before, add end else -- v == false or nil local to_erase for idx,val in pairs(lookup) do -- Assume there is only one match in the dict. if k==val then lookup[k]=nil break end --don't continue after this, next will be confused. end end end mt2.__index = function(t,k) -- looking up a table for idx,val in pairs(lookup) do if k==val then return true end end return false end return setmetatable({},mt2) end end t1 = newDict() t2 = newDict() k1={1,2,3} k2={"a"} k3={"z","d","f"} k1b={1,2,3} k2b={"a"} k3b={"z","d","f"} setmetatable(k1,mt1) setmetatable(k2,mt1) setmetatable(k3,mt1) setmetatable(k1b,mt1) setmetatable(k2b,mt1) setmetatable(k3b,mt1) -- Test multiple entries in 1 dict t1[k1]=true t1[k2]=true assert(t1[k1b],"t1[k1b] did not return true") assert(t1[k2b],"t1[k2b] did not return true") -- Test confusion between 2 dicts t2[k3]=true assert(not t1[k3b],"t1[k3b] did return true") assert(not t2[k1b],"t2[k1b] did return true")
现在可以更快地实现比较,因为现在共同条目只被检查了两次,但你明白我的意思。
由于它严重依赖元表查找,并在每次比较或赋值时需要遍历所有表,因此我无法对其性能进行评论,但由于不想对表进行哈希处理或将它们转换为字符串(又称序列化它们),所以这是唯一的方法。如果我是你,我会认真考虑检查表的序列化而不是采用上述方法。