Documentation for this module may be created at Module:OrderedDict/doc
local LCS = require('Module:LuaClassSystem')
local util_vars = require("Module:VarsUtil")
local util_sort = require("Module:SortUtil")
local OD = {}
local p = LCS.class()
-----------------------------------
-- ordered dict metatable
-----------------------------------
function OD.__ipairs(tbl)
local function stateless_iter(tbl, i)
-- Implement your own index, value selection logic
i = i + 1
local key = tbl[i]
local val = tbl[key]
if key ~= nil and val ~= nil then return i, key, val end
end
-- return iterator function, table, and starting point
return stateless_iter, tbl, 0
end
-- function OD.__pairs(tbl)
-- error('Attempting to call pairs on an ordered dictionary')
-- end
function OD.__newindex(tbl, key, value)
rawset(tbl, #tbl+1, key)
rawset(tbl, key, value)
end
function OD.__index(tbl, key)
if type(key) ~= 'number' then
return rawget(tbl, key)
end
return rawget(tbl, key) -- , rawget(tbl, tbl[key])
end
-----------------------------------
-- class methods
-----------------------------------
function p:init()
rawset(self, "_dict", {})
rawset(self, "_hash", {})
local function __newindex(tbl, key, value)
tbl._dict[key] = value
end
getmetatable(self).__newindex = __newindex
local function __ipairs(tbl)
return ipairs(tbl._dict)
end
getmetatable(self).__ipairs = __ipairs
setmetatable(self._dict, OD)
end
function p:concat(sep, f, ...)
local tbl = {}
for _, _, v in ipairs(self) do
tbl[#tbl+1] = f and f(v, ...) or v
end
return table.concat(tbl, sep or ',')
end
function p:concatKeys(sep, f, ...)
local tbl = {}
for _, k, _ in ipairs(self) do
tbl[#tbl+1] = f and f(k, ...) or k
end
return table.concat(tbl, sep or ',')
end
function p:formatAndConcat(sep, str)
return self:concat(sep, function(val)
return str:format(val)
end)
end
function p:formatAndConcatKeys(sep, str)
return self:concatKeys(sep, function(key)
return str:format(key)
end)
end
function p:get(key)
return self._dict[key]
end
function p:set(key, val)
self._dict[key] = val
self._hash[key] = self._hash[key] or #self._dict
end
function p:mapRows(f, ...)
for _, _, v in ipairs(self) do
f(v, ...)
end
end
function p:mapInPlace(f, ...)
for i, k, v in ipairs(self) do
self:set(k, f(i, k, v, ...))
end
end
function p:removeKey(key)
if not self._hash[key] then return end
self._dict[key] = nil
table.remove(self._dict, self._hash[key])
for i = self._hash[key], #self._dict do
self._hash[self:get(i)] = i
end
self._hash[key] = nil
end
function p:removeIndex(index)
if not self._dict[key] then return end
for i = index, #self._dict do
self._hash[self:get(i)] = i
end
self._hash[index] = nil
self._dict[self:get(index)] = nil
table.remove(self._dict, index)
end
function p:toList()
local ret = {}
for i, _, v in ipairs(self._dict) do
ret[i] = v
end
return ret
end
function p:toDict()
local ret = {}
for i, k, v in ipairs(self._dict) do
ret[i] = k
ret[k] = v
end
return ret
end
function p:sortByKeys(keys, increasing)
util_sort.dictByKeys(self._dict, keys, increasing)
for i, k, _ in ipairs(self._dict) do
self._hash[k] = i
end
end
return p