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?

+3


source to share


2 answers


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.

+2


source


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

      

0


source







All Articles