Module:TableUtil
Jump to navigation
Jump to search
Documentation for this module may be created at Module:TableUtil/doc
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 -- sorts tblToSort to be in the same order as the elements appear in lookup function p.sortByKeyOrder(tblToSort,values) 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.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.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 -- table.remove for non-integer key function p.remove(tbl, 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(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 -- returns a copy of tbl with the elements in opposite order (not a deep copy) function p.reverse(tbl) 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 -- prints the table as a comma-separated list with and function p.printList(tbl) 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 {} 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