[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] = |
+ | 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 |
+ | 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. |
+ | 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