Обход вложенных таблиц в lua - PullRequest
0 голосов
/ 12 июня 2018

Я новичок в lua и мне трудно работать с вложенными структурами данных.

Я пытаюсь написать иерархическую систему, в которой у меня есть таблица из трех ключей, а значения - это другая таблица.Три клавиши верхнего уровня - это зона, регион и окружение в порядке специфичности для меня.Я хочу использовать наиболее конкретное подзначение, присутствующее в таблице, которое относится к ключам переменных моей среды.

Поэтому, учитывая приведенную ниже таблицу данных и переменных среды, я хочу вернуть ключ для региона.US, так как переменная зоны не существует в таблице, хотя, если бы она существовала, это было бы главным приоритетом.Ключ region.US существует и имеет более высокий приоритет, чем окружение, поэтому я должен вернуть ccc.

В зависимости от того, как lua ​​загружает таблицу, я получаю разные результаты, если строка соответствует ключу верхнего уровня.Как я могу сделать это в 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)

Выводы: всегда должен возвращаться 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

1 Ответ

0 голосов
/ 12 июня 2018

Я невероятно смущен, что мне понадобилось так много времени, чтобы понять это.: /

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)
...