如何解决通过路径
从 Reference Dynamic multidimensional table 开始
这样的数据结构local data = {
[1] = {
[1] = { "stuff" },},[2] = {
[1] = { "stuff" },[2] = { "more stuff" },[3] = {
[1] = "deeper stuff"
}
}
}
我添加了以下元数据表
__index = function(t,k)
for i,v in ipairs(k) do
if not t then error("attempt to index nil") end
t = rawget(t,v)
end
return t
end
})
print(data[{2,3,1}]
这对于获取数据非常有用,但是当我尝试设置数据时,它会创建一个新表。例如 data[{2,1}] = "Updated Stuff"
将数据转化为
[1] = {
[1] = { "stuff" }
},[3] = {
[1] = "deeper stuff"
}
},["table: 000001A7E014F570"] = "Updated Stuff"
}
虽然如果我然后调用 print(data[{2,1}]
我得到正确的值但是如果我然后尝试使用 ipairs 递归地循环遍历表我得到原始值并且额外的被忽略。我知道从 Lua 的角度来看这应该是可能的,但只是见树不见林。
我想我正在寻找与 lodash 的 _.set(table,"path.to.key",value)
相当的 Lua
解决方法
print(data[{2,3,1}])
索引数据并因此调用您的 __index
元方法,然后返回字符串 "deeper stuff"
data[{2,1}] = "updated stuff"
是分配索引操作。它会调用 __newindex
,而不是 __index
。
由于您没有 __newindex
,因此您只是使用表 {2,1}
作为表键进行常规分配。
如果要将表的内容用作索引 __newindex
的键,则必须实现 data[2][3][1]
。
我不确定为什么您更喜欢 data[{2,1}]
而不是 data[2][3][1]
。你正在添加不必要的混乱。在表中提供表键很方便的少数情况可以使用一个简单的函数来解决,该函数同时接受表和键列表。但这只是我个人的意见。
我刚刚向您展示了我的最后一个答案是什么。这并不意味着这样做是个好主意:) 抱歉,如果不清楚。
你可以简单地有两个功能:
updateDeep(t,newVal,...)
和 getDeep(t,...)
可以类似于 __index 元方法实现。将 k
替换为 {...}
您还应该实现 __newindex
元方法
local data = {
[1] = {
[1] = { "stuff" },},[2] = {
[1] = { "stuff" },[2] = { "more stuff" },[3] = {
[1] = "deeper stuff"
}
}
}
setmetatable(data,{
__index = function(t,k)
for i,k in ipairs(k) do
if t == nil then return nil end
if type(t) ~= "table" then error("Unexpected subtable",2) end
t = rawget(t,k)
end
return t
end,__newindex = function(t,k,v)
local last_k
for i,k in ipairs(k) do
k,last_k = last_k,k
if k ~= nil then
local parent_t = t
t = rawget(parent_t,k)
if t == nil then
t = {}
rawset(parent_t,t)
end
if type(t) ~= "table" then error("Unexpected subtable",2) end
end
end
rawset(t,last_k,v)
end
})
print(data[{2,1}])
data[{2,1}] = "updated stuff #1"
print(data[{2,1}])
data[{3,1,2}] = "updated stuff #2"
print(data[{3,2}])
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。