Module:User:QFQ/ordered-table

-- see also: local ordered_table = {}

local _v = {} -- key: k, value: v local _k = {} -- key: i, value: k local _i = {} -- key: k, value: i

function ordered_table.insert(t, k, v)	if v == nil then ordered_table.remove(t, k)	else if t[_v][k] == nil then t[_k][#t[_k] + 1] = k			t[_i][k] = #t[_k] end t[_v][k] = v 	end end

function ordered_table.findk(t, k)	return t[_i][k] end

local function find(t, v)	for i, val in ipairs(t) do		if v == val then return i		end end end

-- O(n) function ordered_table.remove(t, k)	local tv = t[_v] local ti = t[_i] local v = tv[k] local i = ti[k] if i then local tk = t[_k] table.remove(tk, i)		for j = i, #tk do			ti[tk[j]] = j		end ti[k] = nil tv[k] = nil end return v end

function ordered_table.pairs(t) local i = 0 return function i = i + 1 local k = t[_k][i] if k ~= nil then return k, t[_v][k] end end end

function ordered_table.index(t, ik) return type(ik) == 'number' and t[_k][ik] or t[_v][ik] end

ordered_table.__newindex = ordered_table.insert ordered_table.__len = function(t) return #t[_k] end ordered_table.__pairs = ordered_table.pairs ordered_table.__index = ordered_table.index

function ordered_table:new(init) init = init or {} local key_table = {} local value_table = {} local index_table = {} local t = { [_k]=key_table, [_v]=value_table, [_i]=index_table } local n = #init if n % 2 ~= 0 then error("key: " .. tostring(init[#init]).. " is missing value", 2) end for i = 1, n/2 do		local k = init[i * 2 - 1] local v = init[i * 2] if value_table[k] ~= nil then error("duplicated key: " .. tostring(k), 2) end key_table[#key_table + 1] = k		index_table[k] = #key_table value_table[k] = v	end return setmetatable(t, self) end

return setmetatable(ordered_table, { __call=ordered_table.new })