在lua中遍历嵌套表

Traversing nested tables in lua

我是lua的新手,并且很难使用嵌套数据结构。

我正在尝试编写一个层次结构系统,其中有一个包含三个键的表,而值是另一个表。按照我的特定顺序,三个顶级键是区域,区域和环境。我想使用表中与我的环境变量的键相关的最具体的子值。

因此,鉴于下面的数据和环境变量表,我想返回region.US的键,因为该表中不存在zone变量,尽管如果这样做的话,将是最高优先级。 key region.US确实存在并且比环境具有更高的优先级,因此我应该返回ccc。

根据lua加载表的方式,我通过匹配顶级键的字符串来获得不同的结果。如何在Lua中做到这一点?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

我的代码无法正常工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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)

输出:应该总是返回ccc

1
2
3
4
5
6
7
8
9
10
11
12
?  lua git:(integration) ? lua test1.lua
gggg
environment:
  staging: fff
  prod: eee
  food: gggg
zone:
  2: bbbbb
  1: aaaaa
region:
  US: ccc
  EU: ddd

...

1
2
3
4
5
6
7
8
9
10
11
12
?  lua git:(integration) ? lua test1.lua
ccc
zone:
  1: aaaaa
  2: bbbbb
region:
  EU: ddd
  US: ccc
environment:
  food: gggg
  prod: eee
  staging: fff

我很尴尬,花了我这么长时间才弄清楚这一点。 :/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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)