Call of Duty Esports Wiki
[checked revision][checked revision]
(Syncing content across wikis)
 
No edit summary
 
(24 intermediate revisions by 4 users not shown)
Line 1: Line 1:
  +
local lang = mw.getLanguage('en')
  +
 
local p = {}
 
local p = {}
  +
  +
function p.generalLength(tbl)
  +
local n = 0
  +
for _, _ in pairs(tbl) do
  +
n = n + 1
  +
end
  +
return n
  +
end
  +
  +
function p.getKeys(tbl, f)
  +
local ret = {}
  +
for k, _ in pairs(tbl) do
  +
ret[#ret+1] = k
  +
end
  +
if f then table.sort(ret, f) end
  +
return ret
  +
end
   
 
function p.keyOf(tbl, val)
 
function p.keyOf(tbl, val)
Line 11: Line 30:
   
 
function p.hash(tbl)
 
function p.hash(tbl)
  +
if not tbl then return {} end
 
local hash = {}
 
local hash = {}
 
for k, v in pairs(tbl) do
 
for k, v in pairs(tbl) do
−
hash[v] = true
+
hash[v] = k
 
end
 
end
 
return hash
 
return hash
 
end
 
end
   
  +
function p.arrayHash(tbl)
−
-- sorts tblToSort to be in the same order as the elements appear in lookup
 
  +
if not tbl then return {} end
−
function p.sortByKeyOrder(tblToSort,lookup)
 
  +
local hash = {}
  +
for k, v in ipairs(tbl) do
  +
hash[v] = k
  +
end
  +
return hash
  +
end
  +
  +
function p.appendHash(parent, tbl)
  +
for k, v in pairs(tbl) do
  +
parent[v] = k
  +
end
  +
return parent
  +
end
  +
  +
function p.sortByKeyOrder(tblToSort,values)
  +
-- sorts tblToSort to be in the same order as the elements appear in lookup
  +
local lookup = p.hash(values)
 
table.sort(tblToSort, function (a,b)
 
table.sort(tblToSort, function (a,b)
−
return (p.keyOf(lookup,a) or 0) < (p.keyOf(lookup,b) or 0)
+
return (lookup[a] or 0) < (lookup[b] or 0)
 
end
 
end
 
)
 
)
Line 27: Line 64:
 
end
 
end
   
  +
function p.uniqueArray(tbl)
−
--[[useful for cargo queries. assumes that each element of tblToSort is itself
 
  +
local hash = {}
−
a table, and sorts the parent table based on some value keyed by 'key' in each row
 
  +
local ret = {}
  +
for _, v in ipairs(tbl) do
  +
if not hash[v] then
  +
hash[v] = true
  +
ret[#ret+1] = v
  +
end
  +
end
  +
return ret
  +
end
   
  +
function p.sortUnique(tbl)
−
by default, if there is no 3rd argument specified, it returns the list in increasing order
 
  +
table.sort(tbl)
  +
local tbl2 = {}
  +
local i = 0
  +
for k, v in ipairs(tbl) do
  +
if v ~= tbl2[i] then
  +
i = i + 1
  +
tbl2[i] = v
  +
end
  +
end
  +
return tbl2
  +
end
   
  +
function p.mergeArrays(tbl1, ...)
−
specify true as a 3rd element to return elements in decreasing order instead ]]
 
  +
-- tbl1 is modified to include the elements of tbl2 appended to the end. Order is preserved.
−
function p.sortByValueInRow(tblToSort, key, increasing)
 
  +
if not tbl1 then tbl1 = {} end
−
table.sort(tblToSort, function (a,b)
 
  +
local newTables = {...}
−
return (a[key] or 0) < (b[key] or 0) and not increasing
 
  +
for _, tbl2 in ipairs(newTables) do
  +
for _, v in ipairs(tbl2) do
  +
tbl1[#tbl1+1] = v
 
end
 
end
−
)
+
end
−
return
+
return tbl1
 
end
 
end
   
−
function p.mergeArrays(tbl1,tbl2)
+
function p.uniqueKeyMergeArrays(key, tbl1, ...)
 
-- tbl1 is modified to include the elements of tbl2 appended to the end. Order is preserved.
 
-- tbl1 is modified to include the elements of tbl2 appended to the end. Order is preserved.
  +
-- skips rows in later tables that have repeat values of a key.
−
for _, v in ipairs(tbl2) do
 
  +
-- useful when unioning Cargo tables with a net groupBy.
−
tbl1[#tbl1+1] = v
 
  +
if not tbl1 then tbl1 = {} end
  +
local newTables = {...}
  +
local seenKeys = {}
  +
for _, tbl2 in ipairs(newTables) do
  +
for _, row in ipairs(tbl2) do
  +
if not seenKeys[row[key]] then
  +
seenKeys[row[key]] = true
  +
tbl1[#tbl1+1] = row
  +
end
  +
end
 
end
 
end
−
return
+
return tbl1
  +
end
  +
  +
function p.merge(tbl1, ...)
  +
-- tbl1 is modified to include all the elements of tbl2.
  +
if not tbl1 then tbl1 = {} end
  +
local tables = {...}
  +
for _, tbl2 in ipairs(tables) do
  +
for k, v in pairs(tbl2) do
  +
tbl1[k] = v
  +
end
  +
end
  +
return tbl1
  +
end
  +
  +
function p.mergeDontOverwrite(tbl1, ...)
  +
-- tbl1 is modified to include all the elements of tbl2.
  +
if not tbl1 then tbl1 = {} end
  +
local tables = {...}
  +
for _, tbl2 in ipairs(tables) do
  +
for k, v in pairs(tbl2) do
  +
if tbl1[k] == nil then
  +
tbl1[k] = v
  +
end
  +
end
  +
end
  +
return tbl1
  +
end
  +
  +
function p.mergeAndConcat(tbl1, sep, ...)
  +
-- tbl1 is modified to include all the elements of tbl2.
  +
if not tbl1 then tbl1 = {} end
  +
local tables = {...}
  +
for _, tbl2 in ipairs(tables) do
  +
for k, v in pairs(tbl2) do
  +
if not tbl1[k] then
  +
tbl1[k] = v
  +
else
  +
tbl1[k] = ('%s%s%s'):format(tbl1[k], sep, v)
  +
end
  +
end
  +
end
  +
return tbl1
  +
end
  +
  +
function p.mergeDicts(tbl1, ...)
  +
-- tbl1 is modified to include the elements of tbl2 appended to the end. Order is preserved.
  +
if not tbl1 then tbl1 = {} end
  +
local newTables = {...}
  +
for _, tbl2 in ipairs(newTables) do
  +
for _, v in ipairs(tbl2) do
  +
tbl1[#tbl1+1] = v
  +
tbl1[v] = tbl2[v]
  +
end
  +
end
  +
return tbl1
 
end
 
end
   
−
-- table.remove for non-integer key
 
 
function p.remove(tbl, key)
 
function p.remove(tbl, key)
  +
-- table.remove for non-numerical key
 
local output = tbl[key]
 
local output = tbl[key]
 
tbl[key] = nil
 
tbl[key] = nil
 
return output
 
return output
  +
end
  +
  +
function p.removeValue(tbl, val)
  +
for k, v in pairs(tbl) do
  +
if val == v then
  +
tbl[k] = nil
  +
end
  +
end
  +
return tbl
  +
end
  +
  +
function p.removeValueFromArray(tbl, val)
  +
local len = #tbl
  +
for i = len, 1, -1 do
  +
if tbl[i] == val then
  +
table.remove(tbl, i)
  +
end
  +
end
  +
end
  +
  +
function p.removeDuplicates(tbl)
  +
local hash = {}
  +
local ret = {}
  +
for _, v in ipairs(tbl) do
  +
if not hash[v] then
  +
hash[v] = true
  +
ret[#ret+1] = v
  +
end
  +
end
  +
return ret
  +
end
  +
  +
function p.removeDuplicateKeys(tbl, key)
  +
-- assumes tbl is an array of tables (rows) that all contain some key `key`
  +
-- edits the original table in place to keep the first copy of each row
  +
-- also returns the table
  +
local hash = {}
  +
local tbl2 = {}
  +
for _, row in ipairs(tbl) do
  +
if not hash[row[key]] then
  +
hash[row[key]] = true
  +
tbl2[#tbl2+1] = row
  +
end
  +
end
  +
for i, _ in ipairs(tbl) do
  +
tbl[i] = tbl2[i]
  +
end
  +
return tbl
  +
end
  +
  +
function p.reverse(tbl)
  +
-- returns a copy of tbl with the elements in opposite order (not a deep copy)
  +
local tbl2 = {}
  +
local len = #tbl
  +
for i = len, 1, -1 do
  +
tbl2[len - i + 1] = tbl[i]
  +
end
  +
return tbl2
  +
end
  +
  +
function p.reverseInPlace(tbl)
  +
local len = #tbl
  +
local stop_at = len / 2
  +
for i = 1, stop_at do
  +
local temp = tbl[i]
  +
tbl[i] = tbl[len - i + 1]
  +
tbl[len - i + 1] = temp
  +
end
  +
end
  +
  +
function p.shallowClone(tbl)
  +
-- mostly to be able to use # operator on something from mw.loadData
  +
local tbl2 = {}
  +
for k, v in pairs(tbl) do
  +
tbl2[k] = v
  +
end
  +
return tbl2
  +
end
  +
  +
function p.slice(tbl, s, e)
  +
if s < 0 then
  +
s = #tbl + 1 + s
  +
end
  +
if e < 0 then
  +
e = #tbl + 1 + e
  +
end
  +
local tbl2 = {}
  +
for k = s, e do
  +
tbl2[#tbl2+1] = tbl[k]
  +
end
  +
return tbl2
  +
end
  +
  +
function p.printList(tbl)
  +
-- prints the table as a comma-separated list with and
  +
if #tbl == 1 then
  +
return tbl[1]
  +
elseif #tbl == 2 then
  +
return table.concat(tbl, ' and ')
  +
else
  +
last = table.remove(tbl, #tbl)
  +
list = table.concat(tbl, ', ')
  +
return list .. ', and ' .. (last or '')
  +
end
  +
end
  +
  +
function p.removeFalseEntries(tbl, max)
  +
if not max then max = #tbl end
  +
local j = 0
  +
for i = 1, max do
  +
if tbl[i] then
  +
j = j + 1
  +
tbl[j] = tbl[i]
  +
end
  +
end
  +
for i = j+1, max do
  +
tbl[i] = nil
  +
end
  +
return tbl
  +
end
  +
  +
function p.padFalseEntries(tbl, max, default)
  +
default = default or ''
  +
for i = 1, max do
  +
if not tbl[i] then
  +
tbl[i] = default
  +
end
  +
end
  +
return tbl
  +
end
  +
  +
function p.concat(tbl, sep, f, ...)
  +
if not tbl then return end
  +
if not sep then sep = ',' end
  +
if not f then
  +
local tbl2 = mw.clone(tbl)
  +
p.removeFalseEntries(tbl2)
  +
return table.concat(tbl2, sep)
  +
end
  +
local tbl2 = {}
  +
for k, v in ipairs(tbl) do
  +
if v then
  +
tbl2[#tbl2+1] = f(v, ...)
  +
end
  +
end
  +
return table.concat(tbl2, sep)
  +
end
  +
  +
function p.concatDict(tbl, sep, f, ...)
  +
local tbl2 = {}
  +
for _, v in ipairs(tbl) do
  +
tbl2[#tbl2+1] = tbl[v]
  +
end
  +
return p.concat(tbl2, sep, f, ...)
  +
end
  +
  +
function p.concatNonempty(tbl, sep, f, ...)
  +
if not tbl then return end
  +
if not next(tbl) then return end
  +
return p.concat(tbl, sep, f, ...)
  +
end
  +
  +
function p.concatFromArgs(args, argname, sep, f)
  +
-- if fields are saved in args as field1, field2, field3, etc
  +
local i = 1
  +
local tbl = {}
  +
if args[argname] then
  +
tbl[1] = args[argname]
  +
i = 2
  +
end
  +
while args[argname .. i] do
  +
tbl[i] = args[argname .. i]
  +
i = i + 1
  +
end
  +
return next(tbl) and p.concat(tbl, sep, f)
  +
end
  +
  +
function p.crop(tbl, max)
  +
for k, _ in ipairs(tbl) do
  +
if k > max then
  +
tbl[k] = nil
  +
end
  +
end
  +
end
  +
  +
function p.alphabetize(tbl)
  +
local hash = {}
  +
local nocase = {}
  +
for i, v in ipairs(tbl) do
  +
nocase[i] = lang:caseFold(v)
  +
hash[nocase[i]] = v
  +
end
  +
table.sort(nocase)
  +
for i, v in ipairs(nocase) do
  +
tbl[i] = hash[v]
  +
end
  +
return tbl
  +
end
  +
  +
function p.guaranteeTable(c, f, ...)
  +
if not c then return nil end
  +
if type(c) == 'table' then
  +
return f and f(c, ...) or c
  +
end
  +
return { f and f(c, ...) or c }
  +
end
  +
  +
function p.guaranteeIndex(tbl, i)
  +
if type(i) == 'number' then return i end
  +
return p.keyOf(tbl, i)
  +
end
  +
  +
function p.concatIfTable(tbl, sep)
  +
if not tbl then return nil end
  +
return p.concat(p.guaranteeTable(tbl), sep)
  +
end
  +
  +
function p.nextNonFalse(tbl)
  +
for _, v in pairs(tbl) do
  +
if v then return v end
  +
end
  +
end
  +
  +
function p.interlace(tbl)
  +
local ret = {}
  +
local _, keyList = next(tbl)
  +
for key, _ in pairs(keyList) do
  +
ret[key] = {}
  +
end
  +
for k, v in pairs(tbl) do
  +
for key, _ in pairs(keyList) do
  +
ret[key][k] = v[key]
  +
end
  +
end
  +
return ret
  +
end
  +
  +
function p.initTable(tbl, key, val)
  +
if tbl[key] then return end
  +
tbl[key] = val or {}
  +
return tbl[key]
  +
end
  +
  +
function p.initDict(tbl, key, val)
  +
if tbl[key] then return end
  +
tbl[key] = val or {}
  +
tbl[#tbl+1] = key
  +
end
  +
  +
function p.push(tbl, val)
  +
-- useful just to make code look cleaner when tbl is something like parent[row.key]
  +
tbl[#tbl+1] = val
  +
end
  +
  +
function p.pushDict(tbl, key, val)
  +
tbl[#tbl+1] = key
  +
tbl[key] = val
  +
end
  +
  +
function p.arrayToDict(tbl, key)
  +
for i, v in ipairs(tbl) do
  +
tbl[v[key]] = v
  +
tbl[i] = v
  +
end
  +
end
  +
  +
function p.extractValueToList(tbl, key)
  +
local ret = {}
  +
for _, v in ipairs(tbl) do
  +
ret[#ret+1] = v[key]
  +
end
  +
return ret
  +
end
  +
  +
function p.extractValueFromDictToList(tbl, key)
  +
local ret = {}
  +
for _, v in ipairs(tbl) do
  +
ret[#ret+1] = tbl[v][key]
  +
end
  +
return ret
  +
end
  +
  +
function p.arrayFromField(tbl, key)
  +
local ret = {}
  +
for k, row in ipairs(tbl) do
  +
ret[#ret+1] = row[key]
  +
end
  +
return ret
 
end
 
end
   

Latest revision as of 12:19, 10 January 2022

To edit the documentation or categories for this module, click here.


local lang = mw.getLanguage('en')

local p = {}

function p.generalLength(tbl)
	local n = 0
	for _, _ in pairs(tbl) do
		n = n + 1
	end
	return n
end

function p.getKeys(tbl, f)
	local ret = {}
	for k, _ in pairs(tbl) do
		ret[#ret+1] = k
	end
	if f then table.sort(ret, f) end
	return ret
end

function p.keyOf(tbl, val)
	for k, v in pairs(tbl) do
		if v == val then
			return k
		end
	end
	return nil
end

function p.hash(tbl)
	if not tbl then return {} end
	local hash = {}
	for k, v in pairs(tbl) do
		hash[v] = k
	end
	return hash
end

function p.arrayHash(tbl)
	if not tbl then return {} end
	local hash = {}
	for k, v in ipairs(tbl) do
		hash[v] = k
	end
	return hash
end

function p.appendHash(parent, tbl)
	for k, v in pairs(tbl) do
		parent[v] = k
	end
	return parent
end

function p.sortByKeyOrder(tblToSort,values)
	-- sorts tblToSort to be in the same order as the elements appear in lookup
	local lookup = p.hash(values)
	table.sort(tblToSort, function (a,b)
			return (lookup[a] or 0) < (lookup[b] or 0)
		end
	)
	return
end

function p.uniqueArray(tbl)
	local hash = {}
	local ret = {}
	for _, v in ipairs(tbl) do
		if not hash[v] then
			hash[v] = true
			ret[#ret+1] = v
		end
	end
	return ret
end

function p.sortUnique(tbl)
	table.sort(tbl)
	local tbl2 = {}
	local i = 0
	for k, v in ipairs(tbl) do
		if v ~= tbl2[i] then
			i = i + 1
			tbl2[i] = v
		end
	end
	return tbl2
end

function p.mergeArrays(tbl1, ...)
	-- tbl1 is modified to include the elements of tbl2 appended to the end. Order is preserved.
	if not tbl1 then tbl1 = {} end
	local newTables = {...}
	for _, tbl2 in ipairs(newTables) do
		for _, v in ipairs(tbl2) do
			tbl1[#tbl1+1] = v
		end
	end
	return tbl1
end

function p.uniqueKeyMergeArrays(key, tbl1, ...)
	-- tbl1 is modified to include the elements of tbl2 appended to the end. Order is preserved.
	-- skips rows in later tables that have repeat values of a key.
	-- useful when unioning Cargo tables with a net groupBy.
	if not tbl1 then tbl1 = {} end
	local newTables = {...}
	local seenKeys = {}
	for _, tbl2 in ipairs(newTables) do
		for _, row in ipairs(tbl2) do
			if not seenKeys[row[key]] then
				seenKeys[row[key]] = true
				tbl1[#tbl1+1] = row
			end
		end
	end
	return tbl1
end

function p.merge(tbl1, ...)
	-- tbl1 is modified to include all the elements of tbl2.
	if not tbl1 then tbl1 = {} end
	local tables = {...}
	for _, tbl2 in ipairs(tables) do
		for k, v in pairs(tbl2) do
			tbl1[k] = v
		end
	end
	return tbl1
end

function p.mergeDontOverwrite(tbl1, ...)
	-- tbl1 is modified to include all the elements of tbl2.
	if not tbl1 then tbl1 = {} end
	local tables = {...}
	for _, tbl2 in ipairs(tables) do
		for k, v in pairs(tbl2) do
			if tbl1[k] == nil then
				tbl1[k] = v
			end
		end
	end
	return tbl1
end

function p.mergeAndConcat(tbl1, sep, ...)
	-- tbl1 is modified to include all the elements of tbl2.
	if not tbl1 then tbl1 = {} end
	local tables = {...}
	for _, tbl2 in ipairs(tables) do
		for k, v in pairs(tbl2) do
			if not tbl1[k] then
				tbl1[k] = v
			else
				tbl1[k] = ('%s%s%s'):format(tbl1[k], sep, v)
			end
		end
	end
	return tbl1
end

function p.mergeDicts(tbl1, ...)
	-- tbl1 is modified to include the elements of tbl2 appended to the end. Order is preserved.
	if not tbl1 then tbl1 = {} end
	local newTables = {...}
	for _, tbl2 in ipairs(newTables) do
		for _, v in ipairs(tbl2) do
			tbl1[#tbl1+1] = v
			tbl1[v] = tbl2[v]
		end
	end
	return tbl1
end

function p.remove(tbl, key)
	-- table.remove for non-numerical key
	local output = tbl[key]
	tbl[key] = nil
	return output
end

function p.removeValue(tbl, val)
	for k, v in pairs(tbl) do
		if val == v then
			tbl[k] = nil
		end
	end
	return tbl
end

function p.removeValueFromArray(tbl, val)
	local len = #tbl
	for i = len, 1, -1 do
		if tbl[i] == val then
			table.remove(tbl, i)
		end
	end
end

function p.removeDuplicates(tbl)
	local hash = {}
	local ret = {}
	for _, v in ipairs(tbl) do
		if not hash[v] then
			hash[v] = true
			ret[#ret+1] = v
		end
	end
	return ret
end

function p.removeDuplicateKeys(tbl, key)
	-- assumes tbl is an array of tables (rows) that all contain some key `key`
	-- edits the original table in place to keep the first copy of each row
	-- also returns the table
	local hash = {}
	local tbl2 = {}
	for _, row in ipairs(tbl) do
		if not hash[row[key]] then
			hash[row[key]] = true
			tbl2[#tbl2+1] = row
		end
	end
	for i, _ in ipairs(tbl) do
		tbl[i] = tbl2[i]
	end
	return tbl
end

function p.reverse(tbl)
	-- returns a copy of tbl with the elements in opposite order (not a deep copy)
	local tbl2 = {}
	local len = #tbl
	for i = len, 1, -1 do
		tbl2[len - i + 1] = tbl[i]
	end
	return tbl2
end

function p.reverseInPlace(tbl)
	local len = #tbl
	local stop_at = len / 2
	for i = 1, stop_at do
		local temp = tbl[i]
		tbl[i] = tbl[len - i + 1]
		tbl[len - i + 1] = temp
	end
end

function p.shallowClone(tbl)
	-- mostly to be able to use # operator on something from mw.loadData
	local tbl2 = {}
	for k, v in pairs(tbl) do
		tbl2[k] = v
	end
	return tbl2
end

function p.slice(tbl, s, e)
	if s < 0 then
		s = #tbl + 1 + s
	end
	if e < 0 then
		e = #tbl + 1 + e
	end
	local tbl2 = {}
	for k = s, e do
		tbl2[#tbl2+1] = tbl[k]
	end
	return tbl2
end

function p.printList(tbl)
	-- prints the table as a comma-separated list with and
	if #tbl == 1 then
		return tbl[1]
	elseif #tbl == 2 then
		return table.concat(tbl, ' and ')
	else
		last = table.remove(tbl, #tbl)
		list = table.concat(tbl, ', ')
		return list .. ', and ' .. (last or '')
	end
end

function p.removeFalseEntries(tbl, max)
	if not max then max = #tbl end
	local j = 0
	for i = 1, max do
		if tbl[i] then
			j = j + 1
			tbl[j] = tbl[i]
		end
	end
	for i = j+1, max do
		tbl[i] = nil
	end
	return tbl
end

function p.padFalseEntries(tbl, max, default)
	default = default or ''
	for i = 1, max do
		if not tbl[i] then
			tbl[i] = default
		end
	end
	return tbl
end

function p.concat(tbl, sep, f, ...)
	if not tbl then return end
	if not sep then sep = ',' end
	if not f then
		local tbl2 = mw.clone(tbl)
		p.removeFalseEntries(tbl2)
		return table.concat(tbl2, sep)
	end
	local tbl2 = {}
	for k, v in ipairs(tbl) do
		if v then
			tbl2[#tbl2+1] = f(v, ...)
		end
	end
	return table.concat(tbl2, sep)
end

function p.concatDict(tbl, sep, f, ...)
	local tbl2 = {}
	for _, v in ipairs(tbl) do
		tbl2[#tbl2+1] = tbl[v]
	end
	return p.concat(tbl2, sep, f, ...)
end

function p.concatNonempty(tbl, sep, f, ...)
	if not tbl then return end
	if not next(tbl) then return end
	return p.concat(tbl, sep, f, ...)
end

function p.concatFromArgs(args, argname, sep, f)
	-- if fields are saved in args as field1, field2, field3, etc
	local i = 1
	local tbl = {}
	if args[argname] then
		tbl[1] = args[argname]
		i = 2
	end
	while args[argname .. i] do
		tbl[i] = args[argname .. i]
		i = i + 1
	end
	return next(tbl) and p.concat(tbl, sep, f)
end

function p.crop(tbl, max)
	for k, _ in ipairs(tbl) do
		if k > max then
			tbl[k] = nil
		end
	end
end

function p.alphabetize(tbl)
	local hash = {}
	local nocase = {}
	for i, v in ipairs(tbl) do
		nocase[i] = lang:caseFold(v)
		hash[nocase[i]] = v
	end
	table.sort(nocase)
	for i, v in ipairs(nocase) do
		tbl[i] = hash[v]
	end
	return tbl
end

function p.guaranteeTable(c, f, ...)
	if not c then return nil end
	if type(c) == 'table' then
		return f and f(c, ...) or c
	end
	return { f and f(c, ...) or c }
end

function p.guaranteeIndex(tbl, i)
	if type(i) == 'number' then return i end
	return p.keyOf(tbl, i)
end

function p.concatIfTable(tbl, sep)
	if not tbl then return nil end
	return p.concat(p.guaranteeTable(tbl), sep)
end

function p.nextNonFalse(tbl)
	for _, v in pairs(tbl) do
		if v then return v end
	end
end	

function p.interlace(tbl)
	local ret = {}
	local _, keyList = next(tbl)
	for key, _ in pairs(keyList) do
		ret[key] = {}
	end
	for k, v in pairs(tbl) do
		for key, _ in pairs(keyList) do
			ret[key][k] = v[key]
		end
	end
	return ret
end

function p.initTable(tbl, key, val)
	if tbl[key] then return end
	tbl[key] = val or {}
	return tbl[key]
end

function p.initDict(tbl, key, val)
	if tbl[key] then return end
	tbl[key] = val or {}
	tbl[#tbl+1] = key
end

function p.push(tbl, val)
	-- useful just to make code look cleaner when tbl is something like parent[row.key]
	tbl[#tbl+1] = val
end

function p.pushDict(tbl, key, val)
	tbl[#tbl+1] = key
	tbl[key] = val
end

function p.arrayToDict(tbl, key)
	for i, v in ipairs(tbl) do
		tbl[v[key]] = v
		tbl[i] = v
	end
end

function p.extractValueToList(tbl, key)
	local ret = {}
	for _, v in ipairs(tbl) do
		ret[#ret+1] = v[key]
	end
	return ret
end

function p.extractValueFromDictToList(tbl, key)
	local ret = {}
	for _, v in ipairs(tbl) do
		ret[#ret+1] = tbl[v][key]
	end
	return ret
end

function p.arrayFromField(tbl, key)
	local ret = {}
	for k, row in ipairs(tbl) do
		ret[#ret+1] = row[key]
	end
	return ret
end

return p