Lua Tables — Searches
Introduction
If you have imported the lulu.table
module as
require 'lulu.table'
then, you can search for particular keys and values in any table
using the following methods.
table.find(tbl,value)
Returns the first key found in tbl
where tbl[key]
is identical in content to value
.
This is a top-level search that returns nil
on failure.
table.contains(tbl,value)
Returns true
if a top-level value in tbl
is identical in content to value
.
table.find_if(tbl,predicate,...)
Returns a key, value, p
trio where p = predicate(value,...)
is not nil
and value = tbl[key]
.
This is a top-level search that returns nil
on failure.
table.find
& table.contains
The table.find
method searches the top-level keys in tbl
for the one whose corresponding value matches the searched-for item. The matches use table.eq
so, if the hunted-for object is a table, we look for one identical in content, not just occupying the same memory blocks.
The search stops on the first match. The concept of “first” is nebulous for general Lua tables, as the elements are stored in an undefined order. The next time you run the search on a table with more than one match, you may get a different key. That will never happen for Lua arrays. |
The table.contains(value)
method is the same as table.find(tbl, value) ~= nil
.
Example
require("lulu.table")
local p = {first = 'Joan', middle = 'Frances', last = 'Doe'}
print("Key for 'Doe':", table.find(p,'Doe'))
Returns the answer Key for 'Doe': last
.
If we have a repeated value in a general table like:
local p = {first = 'Joan', middle = 'Frances', last = 'Doe', other = 'Doe'}
print("Key for 'Doe':", table.find(p,'Doe'))
Then, if you run the code multiple times, you will get both Key for 'Doe': last
and `Key for 'Doe': other
.
If, instead, we have an array of values like:
local p = {'Joan', 'Frances', 'Doe', 'Doe'}
print("Key for 'Doe':", table.find(p,'Doe'))
Then we always get Key for 'Doe': 3
.
table.find_if
The table.find_if(tbl ,predicate,...)
method allows for more complex searches.
It looks for a top-level key
in tbl
such that predicate(tbl[key], ...) ~= nil
.
On success, it returns the trio key, tbl[key], predicate(tbl[key],...)
.
It returns the trio nil, nil, nil
on failure.
The search stops on the first non-nil return from the predicate function. As noted earlier, “first” is nebulous for general Lua tables, as the elements are stored in an undefined order. |
Example: General table
Here, we search for the “first” value in a table that is larger than 42:
local tbl = {foo = 41, boo = 42, bar = 43, baba = 44}
print(table.find_if(tbl, ">", 42))
You will get the trio: bar 43 true or baba 44 true if you run this multiple times. There is no fixed storage order for items in general Lua tables.
We also note that the returned third element will never be of interest in this example.
Example: Lua array
The same example for a Lua array:
local tbl = {41, 42, 43, 44}
print(table.find_if(tbl, ">", 42))
will always output 3 43 true
as the integer keys for Lua arrays are stored in a fixed order.
Predicate Functions
The predicate function can come in one of several forms:
- You can use Lua function like
table.find_if(tbl, function(v) return v > 42 end)
. - You can use a string operator like we did above
table.find_if(tbl, ">", 42)
. - You can use a string lambda like
table.find_if(tbl, "|v| v > 42")
. - You can pass a “table” that is callable, i.e. it has a
__call()
metamethod.
There is more detail on the second and third options in the documentation for the lulu.callable
module.