6
\$\begingroup\$

I have a table structured like this:

UnitScanDB = {
    ["profiles"] = {
        ["Goblin"] = {
            ["Bars"] = {
                {
                    {
                        ["track"] = "Cloak of Shadows#Anti-Magic Shell#Hand of Freedom#Spell Reflection",
                    }, -- [1]
                    {
                        ["track"] = "..."
                    }, -- [2]
                    {
                        ["track"] = "..."
                    }, -- [3]
                }
            }
        }
    }
}

And I would like to convert it to this format:

UnitScanDB = {  
    ["profiles"] = {
        ["Goblin"] = {
            ["Bars"] = {
                {
                    {
                        {
                            ["track"] = "Cloak of Shadows",
                        }, -- [1]
                        {
                            ["track"] = "Anti-Magic Shell",
                        }, -- [2]
                        {
                            ["track"] = "Hand of Freedom",
                        }, -- [3]
                        {
                            ["track"] = "Spell Reflection",
                        }, -- [4]
                    }, -- [1]
                    {
                     --stuff
                    }, -- [2]
                    {
                     --stuff
                    }, -- [3]
                }
            }
        }
    }
}

To do this automatically, I created this function:

function UnitScan:updater()
    local list = db:GetProfiles() 
    for p, name in ipairs(list) do
        local icon = db.profiles[list[p]]["Bars"]
        for x, value in ipairs(icon) do
            for y, value in ipairs(icon[x]) do
                if (icon[x][y].track) then
                    for aura in string.gmatch(icon[x][y].track,"[^#]+") do
                        t = {}
                        t.track = aura
                        tinsert(icon[x][y], t)                  
                    end
                end
            end         
        end 
    end
end

Where

  • db = UnitScanDB
  • db:GetProfiles() = function returns all the keys in "profiles"

Is there a more elegant way to do this without using all those cycles, perhaps using the metatables?

\$\endgroup\$
3
\$\begingroup\$

IMO, there is a cleaner way to do this without even involving metatables. You have a bunch of tables that are nested together that contains some data on each level and you're looking to access and possibility modify a particular branch.

This is not that different from say a HTML DOM tree. This means you can use any standard tree traversal algorithm to find what you're looking for. For example, a table_gsub function(can't think of a better name atm), it takes a table, a string-key you're looking for, and a function to call when a match is found:

function table_gsub(t, selector, f)
    local visit = {}
    for k, v in pairs(t) do
        if type(v) == 'table' then
            table.insert(visit, v)
        end
    end
    if t[selector] then f(t) end
    for _, each in ipairs(visit) do
        table_gsub(each, selector, f)
    end
end

And a convert function to your desire format:

local function convert_format(t)
  assert(type(t.track) == 'string')
  for each in t.track:gmatch "%w[^#]+" do
    table.insert(t, {track = each})
  end
  t.track = nil
end

A simple test to make sure it does the right thing:

table_gsub(profiles, "track", convert_format)
dump(profiles)

It should output something like:

profiles = {
  Goblin = {
    Bars = {
      {
        {
          {
            track = "Cloak of Shadows"
          },
          {
            track = "Anti-Magic Shell"
          },
          {
            track = "Hand of Freedom"
          },
          {
            track = "Spell Reflection"
          }
        },
        {
          track = "..."
        },
        {
          track = "..."
        }
      }
    }
  }
}

You could of course take this idea further with multiple key-string selectors to match against giving you something like jquery-style lua table selection.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.