动态多维表参考

我有一个嵌套表的数据结构,可以深入 N 级。例如

local data = {
  [1] = {
     [1] = { "东西" },
  [2] = {
     [1] = { "东西" },
     [2] = { "更多东西" },
     [3] = {
        [1] = "更深层次的东西"
     }
  }
}

现在我可以通过 data[2][3][1] 引用“更深层次的东西”,但是有没有一种方法可以将 2-3-1 存储为键,以便我可以引用此 data[key] ?

我正在存储一组转换并循环处理的操作,这些操作存储在非规范化的表中。我希望能够引用该特定操作来自原始数据表中的特定位置。由于这是 n 级深的,是否有一种动态编写 [2][3][1]...[n] 的方法?

点赞
用户2858170
用户2858170

你不能拥有单一的多维键。唯一实现这样的方式是使用像 "2-3-1" 这样的字符串,在一个 __index 魔法方法中将其转换为分离的键。

setmetatable(data, {
  __index = function(t, k)
    for index in k:gmatch("%d+") do
        -- insert fancier error handling here
        if not t then error("attempt to index nil") end
        t = rawget(t, tonumber(index))
    end
    return t
  end
  })

  print(data["2-3-1"])

或者你可以使用一个表作为键

setmetatable(data, {
  __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}])

当然在 __index 中还有更多实现表访问的方式。

如果数据是全局变量,你还可以使用 load,做一些像这样的事情

local k = string.gsub("1-1-1", "(%d+)%-?", "[%1]")
local element = load("return data .. k")()

但请不要使数据成为全局变量,只为了这样做。

或者,你可以像 Egor 建议的那样编写不使用元方法的函数......

2021-03-01 07:33:15