Tables
Table Flat
Access and write tables using dot "." notation, also known as "flat path". Similar to TweakDB Flat logic but for any kind of LUA table.
Definitions
tFlat.get(obj: table, path: string, opt default: any) -> value/default
tFlat.has(obj: table, path: string) -> boolean
tFlat.set(obj: table, path: string, value: any) -> table
tFlat.insert(obj: table, path: string, value: any) -> table
tFlat.delete(obj: table, path: string) -> table
Usage examples
All code examples below use this predefined table data. Note that items
is an associative object and elements
is a sequential table.
local myTable = {
ready = true,
config = {
items = {
item1 = true,
item2 = false
},
elements = {
'element1',
'element2'
}
}
}
Get value
local item2 = tFlat.get(myTable, 'config.items.item2')
-- false
local element2 = tFlat.get(myTable, 'config.elements.2')
-- element2
Has value
local hasItem2 = tFlat.has(myTable, 'config.items.item2')
-- true
local hasElement2 = tFlat.has(myTable, 'config.elements.2')
-- true
Set value
tFlat.set(myTable, 'config.items.item2', true)
tFlat.set(myTable, 'config.elements.2', 'newElement2')
myTable = {
["ready"] = true,
["config"] = {
["items"] = {
["item1"] = true,
["item2"] = true,
},
["elements"] = {
"element1",
"newElement2",
},
},
}
Insert sequential table value
tFlat.insert(myTable, 'config.elements', 'element3')
myTable = {
["ready"] = true,
["config"] = {
["items"] = {
["item1"] = true,
["item2"] = false,
},
["elements"] = {
"element1",
"element2",
"element3",
},
},
}
Delete value
tFlat.delete(myTable, 'config.items.item1')
tFlat.delete(myTable, 'config.elements.1')
myTable = {
["ready"] = true,
["config"] = {
["items"] = {
["item2"] = false,
},
["elements"] = {
"element2",
},
},
}
Source code
tFlat = {
get = function(obj, path, default)
-- get path array
path = tFlat.split(path)
-- vars
local length = #path
local current = obj
local key
-- loop through path
for index = 1, length, 1 do
-- current key
key = path[ index ]
-- convert key to number (sequential table)
if tonumber(key) then
key = tonumber(key)
end
-- stop searching if a child object is missing
if current[ key ] == nil then
return default
end
current = current[ key ]
end
return current
end,
has = function(obj, path)
return tFlat.get(obj, path) ~= nil
end,
set = function(obj, path, val)
-- get path array
path = tFlat.split(path)
-- vars
local length = #path
local current = obj
local key
-- loop through path
for index = 1, length, 1 do
-- current key
key = path[ index ]
-- convert key to number (sequential table)
if tonumber(key) then
key = tonumber(key)
end
-- set value on last key
if index == length then
current[ key ] = val
-- current key exists
elseif current[ key ] then
if type(current[ key ]) ~= 'table' then
current[ key ] = {}
end
current = current[ key ]
-- current key doesn't exist
else
current[ key ] = {}
current = current[ key ]
end
end
-- return
return obj
end,
insert = function(obj, path, val)
-- get target
local target = tFlat.get(obj, path)
-- check if table and sequential
if type(target) == 'table' and tFlat.isSequential(target) then
table.insert(target, val)
end
-- return
return obj
end,
delete = function(obj, path)
-- get path array
path = tFlat.split(path)
-- vars
local length = #path
local current = obj
local key
-- loop through path
for index = 1, length, 1 do
-- current key
key = path[ index ]
-- convert key to number (sequential table)
if tonumber(key) then
key = tonumber(key)
end
-- set value on last key
if index == length then
current[ key ] = nil
else
current = current[ key ] or {}
end
end
-- return
return obj
end,
split = function(s)
s = tostring(s)
local fields = {}
local pattern = string.format("([^%s]+)", '.')
string.gsub(s, pattern, function(c)
fields[ #fields + 1 ] = c
end)
return fields
end,
isSequential = function(array)
for k, _ in pairs(array) do
if type(k) ~= "number" then
return false
end
end
return true
end,
}
Last updated