patternMinor
String split and tables
Viewed 0 times
andsplitstringtables
Problem
I have a table structured like this:
And I would like to convert it to this format:
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)
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)
Solution
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
And a convert function to your desire format:
A simple test to make sure it does the right thing:
It should output something like:
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.
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
endAnd 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
endA 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.
Code Snippets
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
endlocal 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
endtable_gsub(profiles, "track", convert_format)
dump(profiles)profiles = {
Goblin = {
Bars = {
{
{
{
track = "Cloak of Shadows"
},
{
track = "Anti-Magic Shell"
},
{
track = "Hand of Freedom"
},
{
track = "Spell Reflection"
}
},
{
track = "..."
},
{
track = "..."
}
}
}
}
}Context
StackExchange Code Review Q#70591, answer score: 3
Revisions (0)
No revisions yet.