How to search for Lua table values
I have a project that requires a relational database such as a structure in an environment where an actual database is not possible. The language is limited to Lua, which is far from the strongest language. I have a table of tables with a structure like this:
table={
m:r={
x=1
y=1
displayName="Red"
}
m:y={
x=1
y=2
displayName="Yellow"
}
}
Creating, storing and retrieving a table is straightforward. Where I run into problems is searching. For clarity, if I could use SQL, I would do this:
SELECT * FROM table WHERE displayName="Red"
Is there a Lua function that will allow me to search this way?
source to share
An easy way is to iterate over all the elements and find what matches your criteria:
local t={
r={
x=1,
y=1,
displayName="Red",
},
y={
x=1,
y=2,
displayName="Yellow",
},
}
for key, value in pairs(t) do
if value.displayName == 'Red' then
print(key)
end
end
This should print 'r'.
This can be quite slow on large tables. To speed up this process, you can track links in a hash , which will provide much faster access. Something like this might work:
local cache = {}
local function findValue(key)
if cache[key] == nil then
local value
-- do a linear search iterating through table elements searching for 'key'
-- store the result if found
cache[key] = value
end
return cache[key]
end
If the elements in the table change their values, you will need to invalidate the cache when updating or deleting values.
source to share
There are no built-in functions for finding tables. There are many ways to do this, which vary in complexity and effectiveness.
local t = {
r={displayname="Red", name="Ruby", age=15, x=4, y=10},
y={displayname="Blue", name="Trey", age=22, x=3, y=2},
t={displayname="Red", name="Jack", age=20, x=2, y=3},
h={displayname="Red", name="Tim", age=25, x=2, y=33},
v={displayname="Blue", name="Bonny", age=10, x=2, y=0}
}
In Programming in Lua, they recommend creating a reverse table for efficient lookups.
revDisplayName = {}
for k,v in pairs(t) do
if revDisplayName[v.displayname] then
table.insert(revDisplayName[v.displayname], k)
else
revDisplayName[v] = {k}
end
end
Then you can easily match the display names.
for _, rowname in pairs(revDisplayName["Red"]) do
print(t[rowname].x, t[rowname].y)
end
There is code for making SQL-like queries in Lua, on Lua tables, in Getting Started Lua Programming if you want to create complex queries.
If you just want to find multiple records to match, you can abstract the search using an iterator in Lua
function allmatching(tbl, kvs)
return function(t, key)
repeat
key, row = next(t, key)
if key == nil then
return
end
for k, v in pairs(kvs) do
if row[k] ~= v then
row = nil
break
end
end
until row ~= nil
return key, row
end, tbl, nil
end
which you can use like this:
for k, row in allmatching(t, {displayname="Red", x=2}) do
print(k, row.name, row.x, row.y)
end
which prints
h Tim 2 33
t Jack 2 3
source to share