Module:UtilsTable

local lang = mw.getLanguage('en')

local p = { inspect = require("Module:UtilsTable/Inspect") }

function p.keys(tbl) local keyset = {} for k in pairs(tbl) do     keyset[#keyset + 1] = k   end return keyset end

function p.values(tbl) local valueset = {} for _, v in pairs(tbl) do     table.insert(valueset, v)   end return valueset 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) local hash = {} for k, v in pairs(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.groupBy(key, tbl) if not key then return tbl end local result = {} for _, v in ipairs(tbl) do		local groupingKey = v[key] or "" local group = result[groupingKey] or {} table.insert(group, v)		result[groupingKey] = group end return result end

-- Inspired by https://lodash.com/docs/4.17.15#takeWhile function p.takeWhile(property, tbl) local results = {} local i = 1 while tbl[i] and tbl[i][property] do		table.insert(results, tbl[i]) i = i + 1 end return results end function p.filter(property, tbl) local results = {} for _, val in ipairs(tbl) do		if val[property] then table.insert(results, val) end end return results 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

-- @param Returns a new array grouping together the values of the arrays given. Order is preserved. function p.mergeArrays(...) local merged = {} for _, tbl in ipairs(arg) do		for _, v in ipairs(tbl) do			merged[#merged+1] = v		end end return merged end

function p.merge(tbl1, tbl2) -- tbl1 is modified to include all the elements of tbl2. if not tbl1 then tbl1 = {} end if not tbl2 then tbl2 = {} end for k, v in pairs(tbl2) do		tbl1[k] = v	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

-- 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)	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.mapInPlace(tbl, f, max) for k, v in pairs(tbl) do		tbl[k] = f(v) end return tbl end

function p.mapSafe(tbl, f)	local tbl2 = mw.clone(tbl) p.removeFalseEntries(tbl2) for k, v in ipairs(tbl2) do		tbl2[k] = f(v) end return tbl2 end

function p.mapRowsInPlace(tbl, f)	for k, row in ipairs(tbl) do		f(row) end return tbl end

function p.mapDictRowsInPlace(tbl, f)	for _, v in ipairs(tbl) do		f(tbl[v]) end return tbl end

function p.concat(tbl, sep, f, max) -- f is a function that doesn't take any additional args if f then p.mapInPlace(tbl, f)	else p.removeFalseEntries(tbl, max) end return table.concat(tbl, sep) end

function p.concatSafe(tbl, sep, f) -- f is a function that doesn't take any additional args local tbl2 = mw.clone(tbl) if f then p.mapInPlace(tbl2, f)	else p.removeFalseEntries(tbl2) end return table.concat(tbl2, sep) 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

-- Returns the list with duplicate values removed. function p.removeDuplicates(list) local hash = {} local result = {}

for key, value in pairs(list) do		if (not hash[value]) then result[#result+1] = value hash[value] = true end end return result end

-- Returns the biggest table among all tables provided function p.GetBiggestTable(tables) local result = tables[0] for key, tbl in ipairs(tables) do		if #tbl > #result then result = tbl end end return result end

return p