Extra Table Functions

Post Reply
Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Extra Table Functions

Post by Jor'Mox »

I like extending the options available in the included table functions to make certain behaviors easier to accomplish. And since I already have them on hand, I might as well share them, in case anyone else has a use for them.

This function lets you use table functions as methods of whatever table you pass it. Also, if you pass it multiple arguments, it forms them into a table that can be used this way and returns it. This will preserve the existing metatable for the table you pass it, if there is on, changing only the __index element.
Code: [show] | [select all] lua
function table.meta(...)
    local tbl
    if type(arg[1]) == "table" and not arg[2] then
        tbl = arg[1]
    else
        tbl = arg
        tbl.n = nil
    end
    local meta = getmetatable(tbl) or {}
    meta.__index = table
    setmetatable(tbl,meta)
    return tbl
end
The next three functions all let you use indexes not actually in the table, rounding down, up, or to the closest existing index, and returning the associated value. This will preserve the existing metatable for the table you pass it, if there is on, changing only the __index element.

This one rounds down.
Code: [show] | [select all] lua
function table.use_floor(tbl)
    local func = function (self,key)
        local max
        for k,v in pairs(self) do
            if tonumber(k) and k < key then
                if not max then
                    max = k
                elseif k > max then
                    max = k
                end
            end
        end
        return (max and self[max]) or nil
    end
    local meta = getmetatable(tbl) or {}
    meta.__index = func
    setmetatable(tbl,meta)
end
This rounds up.
Code: [show] | [select all] lua
function table.use_ceil(tbl)
    local func = function (self,key)
        local min
        for k,v in pairs(self) do
            if tonumber(k) and k > key then
                if not min then
                    min = k
                elseif k < min then
                    min = k
                end
            end
        end
        return (min and self[min]) or nil
    end
    local meta = getmetatable(tbl) or {}
    meta.__index = func
    setmetatable(tbl,meta)
end
And this rounds to the nearest.
Code: [show] | [select all] lua
function table.use_round(tbl)
    local func = function (self,key)
        local closest
        for k,v in pairs(self) do
            if tonumber(k) then
                if not closest then
                    closest = k
                elseif math.abs(key - closest) > math.abs(key - k) then
                    closest = k
                end
            end
        end
        return (closest and self[closest]) or nil
    end
    local meta = getmetatable(tbl) or {}
    meta.__index = func
    setmetatable(tbl,meta)
end
More additions are likely to follow.

Post Reply