Search code examples
lualua-table

Lua Table - Search for Items that starts with an Letter


i have this table

    animals = {
     {sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
     {sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
     {sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324
}

there i can search by a listed entry

for _,v in pairs(animals) do
  if v.sname == "bunny" then
    print(v.sname, v.name, v.size, v.size2, v.size3)
    break
  end
end

and get the result:

bunny   bunny hase  4   8   9

Now i want to search in my table by starting with a single Letter, for example "b", that show me all the entries starting with the letter "b" to get the same result?

I found no Solution. May you can help me?


Solution

  • First: The table animals needs a trailing } ;-)

    Put it in a Lua -i console and play around with...

    >animals = {                                   
         {sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
         {sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
         {sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324}
    }
    -- Now set a __call metamethod on same table
    >setmetatable(animals,{__call=function(tab,...)
    local args={...}
    for key, value in pairs(tab) do
    if value.sname:find(args[1],1) then print(key,'=',value.sname) end
    end
    end})
    table: 0x565c4a00
    -- Lets try it once
    >animals('b')                                  
    1    =    bunny
    -- Next one
    >animals('c')
    3    =    cow
    -- Last one
    >animals('m')
    2    =    mouse
    

    Using metatables holds your stuff together.
    Another fine place is the __index metamethod that can hold all functions you need for that table and can be used like the string functions on a string.
    ( Like: value.sname:find(args[1],1) )
    This leads to the heart of what find should do.
    In first example it looks in whole sname for a matching pattern.
    Check the Lua patterns what also can be useful.
    Maybe a ^ only for the begining sounds smart?
    So construct the find pattern: '^'..args[1]
    ...and use more than one letter if you have a cow, crow, frog and fish in your animals.

    Example with function name find in __index

    >animals = {                                   
         {sname = "bunny", name = "bunny hase", size = 4, size2 = 8, size3 = 9},
         {sname = "mouse", name = "Micky Mouse", size = 1, size2 = 12, size3 = 22},
         {sname = "cow", name = "Die Kuh", size = 30, size2 = 33, size3 = 324}
    }
    -- Place a find function into __index
    >setmetatable(animals,{__index={find=function(tab,...)
    local args={...}
    for key, value in pairs(tab) do
    if value.sname:find('^'..args[1]) then print(key,'=',value.sname) end
    end
    end}})
    table: 0x565c3db0
    -- first
    >animals:find('c')                                
    3       =       cow
    -- next
    >animals:find('m')
    2       =       mouse
    -- last
    >animals:find('b')
    1       =       bunny
    

    If you like to print all key values then extend the print() in find().