Module:OrderedDict

local Class = require('Module:Class').Class local util_vars = require("Module:VarsUtil") local util_sort = require("Module:SortUtil")

local OD = {} local p = 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:new 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