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.
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.
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.
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.
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.