微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

通过路径

如何解决通过路径

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 举报,一经查实,本站将立刻删除。