检查Lua表的成员是否存在于任何级别
2015-6-7 1:31:47
收藏:0
阅读:96
评论:6
我需要检查一个成员是否存在于一个不在下一级,而是沿着成员路径的表中。
foo = {}
if foo.bar.joe then
print(foo.bar.joe)
end
这会造成一个 attempt to index field 'bar' (a nil value) 错误,因为 bar 没有定义。
我的通常解决方案是逐个测试链条。
foo = {}
if foo.bar and foo.bar.joe then
print(foo.bar.joe)
end
但是当有许多嵌套的表格时,这可能会非常繁琐。是否有比逐个进行测试更好的方法?
点赞
用户1847592
```lua
debug.setmetatable(nil, {__index = {}})
foo = {}
print(foo.bar.baz.quux)
print(({}).prd.krt.skrz.drn.zprv.zhlt.hrst.zrn) -- sorry ))
将以上 Lua 代码翻译成中文并且保留原本的 markdown 格式:
debug.setmetatable(nil, {__index = {}})
foo = {}
print(foo.bar.baz.quux)
print(({}).prd.krt.skrz.drn.zprv.zhlt.hrst.zrn) -- 对不起 ))
2015-06-07 09:16:47
用户1288130
我认为你正在寻找以下代码:
local function get(Obj, Field, ...)
if Obj == nil or Field == nil then
return Obj
else
return get(Obj[Field], ...)
end
end
local foo = {x = {y = 7}}
assert(get() == nil)
assert(get(foo) == foo)
assert(get(foo, "x") == foo.x)
assert(get(foo, "x", "y") == 7)
assert(get(foo, "x", "z") == nil)
assert(get(foo, "bar", "joe") == nil)
assert(get(foo, "x", "y") or 41 == 7)
assert(get(foo, "bar", "joe") or 41 == 41)
local Path = {foo, "x", "y"}
assert(get(table.unpack(Path)) == 7)
get 函数简单地遍历给定的路径,直到遇到 nil 值为止。看起来很完美。当然你可以考虑一个比 “get” 更好的函数名。
和 or 连用时要当心。
我很佩服 Egor 聪明的答案,但一般来说,我们不应该依赖这种技巧。
参见
Lua 5.2 的“安全表导航”补丁:http://lua-users.org/wiki/LuaPowerPatches
关于此问题的长时间讨论:http://lua-users.org/lists/lua-l/2010-08/threads.html#00519
我怀疑 MetaLua 中已经实现了相关的内容,但我目前找不到。
2015-06-07 17:33:42
用户3735873
如果我正确理解了您的问题,这里有一个可能性:
function isField(s)
local t
for key in s:gmatch('[^.]+') do
if t == nil then
if _ENV[ key ] == nil then return false end
t = _ENV[ key ]
else
if t[ key ] == nil then return false end
t = t[ key ]
end
--print(key) --for DEBUGGING
end
return true
end
-- To test
t = {}
t.a = {}
t.a.b = {}
t.a.b.c = 'Found me'
if isField('t.a.b.c') then print(t.a.b.c) else print 'NOT FOUND' end
if isField('t.a.b.c.d') then print(t.a.b.c.d) else print 'NOT FOUND' end
更新:根据 cauterite 的建议,这里有一个版本,它也可以处理局部变量,但需要传入两个参数 :(
function isField(t,s)
if t == nil then return false end
local t = t
for key in s:gmatch('[^.]+') do
if t[ key ] == nil then return false end
t = t[ key ]
end
return true
end
-- To test
local
t = {}
t.a = {}
t.a.b = {}
t.a.b.c = 'Found me'
if isField(t,'a.b.c') then print(t.a.b.c) else print 'NOT FOUND' end
if isField(t,'a.b.c.d') then print(t.a.b.c.d) else print 'NOT FOUND' end
2015-06-07 20:14:36
用户4988149
foo = {}
foo.boo = {}
foo.boo.jeo = {}
foo.boo.joe is foo['boo']['joe'] and so
i make next function
function exist(t)
local words = {}
local command
for i,v in string.gmatch(t, '%w+') do words[#words+1] = i end
command = string.format('a = %s', words[1])
loadstring(command)()
if a == nil then return false end
for count=2, #words do
a = a[words[count]]
if a == nil then return false end
end
a = nil
return true
end
foo = {}
foo.boo = {}
foo.boo.joe = {}
print(exist('foo.boo.joe.b.a'))
使用 loadstring 函数创建临时变量。我的 Lua 版本是 5.1。
在 5.2 或 5.3 中移除 loadstring 函数,改用 load。
2015-06-13 09:45:04
用户1878009
要搜索表中在任意层级上的元素,我会使用以下的方法:
function exists(tab, element)
local v
for _, v in pairs(tab) do
if v == element then
return true
elseif type(v) == "table" then
return exists(v, element)
end
end
return false
end
testTable = {{"胡萝卜", {"蘑菇", "生菜"}, "蛋黄酱"}, "肉桂"}
print(exists(testTable, "蘑菇")) -- true
print(exists(testTable, "苹果")) -- false
print(exists(testTable, "肉桂")) -- true
2015-06-14 06:01:11
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在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中获取用户配置主目录的跨平台方法
我不明白你所说的“沿着成员路径”的意思。从例子中看,我猜想你是想在一个“子表”中查找一个值?
local function search(master, target) --target is a string for k,v in next, master do if type(v)=="table" and v[target] then return true end end end举一个简单的例子。如果您使用这样的函数,您可以传递
foo表和joe字符串来查看foo.*.joe是否存在。希望这对您有所帮助。