遍历 lua 中的嵌套表

Traversing nested tables in lua

我是 lua 的新手,在使用嵌套数据结构方面遇到困难。

我正在尝试编写一个层次结构系统,其中我有一个 table 三个键,值是另一个 table。三个顶级键是 zone、region 和 environment,按我的特定顺序排列。我想使用 table 中与我的环境变量的键相关的最具体的子值。

所以鉴于 table 下面的数据和环境变量,我想 return region.US 的键,因为 table 中不存在区域变量,尽管如果这样做,那将是重中之重。密钥 region.US 确实存在并且优先级高于环境,因此我应该 return ccc.

根据 lua 加载 table 的方式,我通过匹配顶级键的字符串得到不同的结果。我如何在 Lua 中执行此操作?

env_zone = 5  -- doesn't exist in table, but should return if it did
env_region = US  -- exists and should return because env_zone doesn't exist
env_environment = food  -- does exist but should not be returned because env_region is a higher priority


zone:
  1: aaaaa
  2: bbbbb
region:
  EU: ddd
  US: ccc
environment:
  food: gggg
  prod: eee
  staging: fff

我的代码不能正常工作。

local cjson = require('cjson')

function tprint (tbl, indent)
  if not indent then indent = 0 end
  for k, v in pairs(tbl) do
    formatting = string.rep("  ", indent) .. k .. ": "
    if type(v) == "table" then
      print(formatting)
      tprint(v, indent+1)
    elseif type(v) == 'boolean' then
      print(formatting .. tostring(v))
    else
      print(formatting .. v)
    end
  end
end

local function slurp(path)
    local f = io.open(path)
    local s = f:read("*a")
    f:close()
    return s
end

local json_string = slurp("data.json")
local tab = cjson.decode(json_string)

local zone_var = os.getenv("zone")   -- "fake"
local region_var = os.getenv("region") -- "US"
local env_var = os.getenv("env")     -- "food"

local ok, err = pcall(
  function ()
    for key, value in pairs(tab) do
      if string.match(key, "zone") then --highest priority, check it first
        for subkey, subvalue in pairs(value) do
          if string.match(subkey, zone_var) then
            print(subvalue)
            return
          end
        end
      elseif string.match(key, "region") then --second highest priority
        for subkey, subvalue in pairs(value) do
          if string.match(subkey, region_var) then
            print(subvalue)
            return
          end
        end
      elseif string.match(key, "environment") then --last chance
        for subkey, subvalue in pairs(value) do
          if string.match(subkey, env_var) then
            print(subvalue)
            return
          end
        end
      end
    end
  end
)
tprint(tab)

输出:应该总是returning ccc

➜  lua git:(integration) ✗ lua test1.lua
gggg
environment:
  staging: fff
  prod: eee
  food: gggg
zone:
  2: bbbbb
  1: aaaaa
region:
  US: ccc
  EU: ddd

...

➜  lua git:(integration) ✗ lua test1.lua
ccc
zone:
  1: aaaaa
  2: bbbbb
region:
  EU: ddd
  US: ccc
environment:
  food: gggg
  prod: eee
  staging: fff

我花了这么长时间才弄明白这一点,我感到非常尴尬。 :/

local cjson = require('cjson')

function tprint (tbl, indent)
  if not indent then indent = 0 end
  for k, v in pairs(tbl) do
    formatting = string.rep("  ", indent) .. k .. ": "
    if type(v) == "table" then
      print(formatting)
      tprint(v, indent+1)
    elseif type(v) == 'boolean' then
      print(formatting .. tostring(v))
    else
      print(formatting .. v)
    end
  end
end

local function slurp(path)
    local f = io.open(path)
    local s = f:read("*a")
    f:close()
    return s
end

local json_string = slurp("data.json")
local tab = cjson.decode(json_string)

local zone_var = os.getenv("zone")
local region_var = os.getenv("region")
local env_var = os.getenv("environment")

local ok, err = pcall(
  function()
    for key, value in pairs(tab.zone) do
      if string.match(key, zone_var) then
        print(value)
        return
      end
    end
    for key, value in pairs(tab.region) do
      if string.match(key, region_var) then
        print(value)
        return
      end
    end
    for key, value in pairs(tab.environment) do
      if string.match(key, environment_var) then
        print(value)
        return
      end
    end
  end
)

tprint(tab)