Table Functions - Lua

Post Reply
User avatar
Rakon
Posts: 350
Joined: Tue Feb 16, 2010 7:41 pm
Contact:

Table Functions - Lua

Post by Rakon » Mon Mar 22, 2010 5:10 am

I utilize tables a lot within my system, but I am used to Python's table and dictionary types. Unfortunatly, Lua does not have standard ways to manipulate data in a table the way I am used to. (Or at least, none that I have found yet, natively)
I have a few functions that work well for giving a bit of functionality to table searching/sorting. Hope this is useful to some others!
Code: [show] | [select all] lua

-- Table functions
function tcount(tt, item) 
-- Count the occurrence of 'item' in table
 local count
 count = 0
 for ii,xx in pairs(tt) do
   if item == xx then count = count + 1 end
 end -- for
 return count
end -- tcount

function __genOrderedIndex( t )
-- Generates index for ordering a table
-- DO NOT CALL THIS FUNCTION
    local orderedIndex = {}
    for key in pairs(t) do
        table.insert( orderedIndex, key )
    end
    table.sort( orderedIndex )
    return orderedIndex
end -- genOrderedIndex

function orderedNext(t, state)
-- Same as 'next' function, except returns the keys in the alphabetic order
    if state == nil then
        --generate index
        t.__orderedIndex = __genOrderedIndex( t )
        key = t.__orderedIndex[1]
        return key, t[key]
    end
    key = nil
    for i = 1,table.getn(t.__orderedIndex) do
        if t.__orderedIndex[i] == state then
            key = t.__orderedIndex[i+1]
        end
    end

    if key then
        return key, t[key]
    end

    t.__orderedIndex = nil
    return
end -- orderedNext

function orderedPairs(t)
    -- Call THIS function
    return orderedNext, t, nil
end -- orderedPairs


function tfind(tbl, value)
 -- Find out the position of an element within a list. Needed in order to REMOVE that element
 for k,v in ipairs(tbl) do
  if v == value then
   return k
  end
 end
 return nil
end -- tfind
-- end table functions

I also wanted to ask about Lua tables as variables, and Mudlet's saving of them.
I've tried creating a test table, as a variable and saving it via 'remember('table_var')'.
I then close Mudlet completely, reopen it, and then issue 'loadVars()' and try to access that table that was saved.
This fails, with the table being a 'nil' instead of any table existing.

I've managed to work around this by using table.save() and table.load() for saving my table Variables, but this is extremely cumbersome and using external files to save internal variables is inefficient. Would there be a way to save the table variables WITH Mudlet's 'remember()' command, or another way that would ensure the table would be properly initiated instead of using table.save() and load()? I'd like to minimize the external files I'm using, and would really rather not have them at all for the many table instances I'll be creating.

Thanks.

User avatar
tsuujin
Posts: 695
Joined: Fri Feb 26, 2010 12:59 am
Location: California
Contact:

Re: Table Functions - Lua

Post by tsuujin » Mon Mar 22, 2010 6:22 am

Lua tables are great for certain things, and cumbersome for others. My gripe with them is that they don't save the order they're entered in, unless you explicitly tell it to via numbered index.

lua-users wiki was kind enough to provide a workaround using metatables that creates a table which functions like a PHP table (something I'm more familiar with). Here's the code, along with my personal changes.

[syntax=lua]
-- Make a table that behaves like PHP tables, retaining the order elements are entered in.

if not php then php = {} end

function php:Table(...)
local newTable,keys,values={},{},{}
newTable.pairs=function(self) -- pairs iterator
local count=0
return function()
count=count+1
return keys[count],values[keys[count]]
end
end
newTable.count=function(self) -- count return
return table.getn(keys)
end
setmetatable(newTable,{
__newindex=function(self,key,value)
if not self[key] then table.insert(keys,key)
elseif value==nil then -- Handle item delete
local count=1
while keys[count]~=key do count = count + 1 end
table.remove(keys,count)
end
values[key]=value -- replace/create
end,
__index=function(self,key) return values[key] end
})
return newTable
end
[/syntax]

API:
Create a new table:

Code: Select all

var = php:Table()
Enter a table element:

Code: Select all

var[key] = value
ie:
var["mykey"] = "This is a test"
Return a count of the number of elements:

Code: Select all

var:count()
Iterate through a list:

Code: Select all

for i,v in var:pairs() do
    echo("\n"i..": "..v.."\n")
end
Maybe this will make working with tables a bit easier for you, but it doesn't solve the issue of saving or loading them

guy
Posts: 26
Joined: Wed Mar 03, 2010 5:41 am
Location: Seattle

Re: Table Functions - Lua

Post by guy » Tue Mar 23, 2010 5:44 am

Thanks for sharing this, Rakon. For others reading this, there are also other ways to do sorted iteration, Rakon just listed the first method from lua-users.org/wiki/SortedIteration.

That way is atrociously slow due to the inefficient inner loop of orderedNext(). In my test, a speed-up of nearly a 1000 fold can be achieved by using __genOrderedIndex directly in the following way:
Code: [show] | [select all] lua
local j = 0
local table = {... whatever}
for _,key in ipairs(__genOrderedIndex( table )) do
   val = table[key]
   print(key, val) -- or whatever else needs to be done with these sorted keys/values.
end
An additional couple percent more efficiency can be eked out by replacing the line
Code: [show] | [select all] lua
table.insert( orderedIndex, key )
with
Code: [show] | [select all] lua
orderedIndex[#orderedIndex + 1] = key
My sample data are from my local /usr/share/dict/words file sorted in random order and split into key/value pairs, stored as table1. My particular dict has ~100k words that were pruned of non-alphanumeric characters prior to being used in the table.

I've attached the code I used. File extensions are .xml so they could be uploaded, but both are actually plain lua source.
Attachments
longlist.xml
contains definition for table1 as used by speedtest
(1.1 MiB) Downloaded 265 times
speedtest.xml
This is the benchmarking code including modified __genOrderedIndex. Rename to .lua if it makes you happy, has no xml markup.
(2.65 KiB) Downloaded 233 times

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests