Anonymous
×
Create a new article
Write your page title here:
We currently have 194 articles on The Dream Shrine. Type your article name above or click on one of the titles below and start writing!



The Dream Shrine
194Articles

Documentation for this module may be created at Module:UtilsTable/doc

local p = {}
local h = {}

-- HELPERS

function h.append(tbl, val)
	tbl[table.maxn(tbl)+1] = val
end

function h.mapper(iteratee)
	if type(iteratee) == "function" then
		return iteratee
	end
	if type(iteratee) == "string" or type(iteratee) == "number" then
		return p._property(iteratee) 
	end
end

function h.predicate(iteratee)
	if type(iteratee) == "function" then
		return iteratee
	end
	if type(iteratee) == "string" or type(iteratee) == "number" then
		return p._property(iteratee)
	end
	if type(iteratee) == "table" then
		return p._isMatch(iteratee)
	end
	return iteratee
end

-- GENERAL

function p.clone(val)
	if type(val) ~= "table" then
		return val
	end
	local result = {}
	for k, v in pairs(val) do
		result[k] = v
	end
	return result
end

function p.cloneDeep(val)
	if type(val) ~= "table" then
		return val
	end
	return p.merge({}, val)
end

function p.hasArray(tbl)
	if type(tbl) ~= "table" then
		return false
	end
	return p.size(tbl) == 0 or p.len(tbl) > 0
end

function p.hasKey(tbl, key)
	return p._hasKey(key)(tbl)
end
function p._hasKey(key)
	return function(tbl)
		return not not tbl[key]
	end
end

function p.invert(tbl)
	local inverted = {}
	for k, v in pairs(tbl) do
		inverted[v] = k
	end
	return inverted
end

function p.isArray(tbl)
	if type(tbl) ~= "table" then
		return false
	end
	for k, v in pairs(tbl) do
		if type(k) ~= "number" then
			return false
		end
	end
	return true
end

function p.isEmpty(tbl)
	return p.size(tbl) == 0
end

function p.isEqual(tbl, other)
	return p._isEqual(tbl)(other)
end
function p._isEqual(tbl)
	return function(other)
		if type(tbl) ~= "table" or type(other) ~= "table" then
			return tbl == other
		end
		return p.isMatch(other, tbl) and p.isMatch(tbl, other)
	end
end

function p.isMatch(tbl, source)
	return p._isMatch(source)(tbl)
end
function p._isMatch(sourceTbl)
	return function(tbl)
		if sourceTbl == tbl then
			return true
		end
		if type(sourceTbl) ~= type(tbl) then
			return false
		end
		if p.size(sourceTbl) == 0 and p.size(tbl) > 0 then
			return false
		end
		for k, v in pairs(sourceTbl) do
			if type(v) ~= "table" and v ~= tbl[k] then
				return false
			end
			if type(v) == "table" and not p.isMatch(tbl[k], v) then
				return false
			end
		end
		return true
	end
end

function p.ivalues(tbl)
	local result = {}
	for _, v in ipairs(tbl) do
		table.insert(result, v)
	end
	return result
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.keys(tbl)
   local result = {}
   for k in pairs(tbl) do
   		h.append(result, k)
   end
   return result
end

function p.mapValues(tbl, iteratee)
	return p._mapValues(iteratee)(tbl)
end
function p._mapValues(iteratee)
	local mappingFunction = h.mapper(iteratee)
	return function(tbl)
		local result = {}
		for k, v in pairs(tbl) do
			result[k] = mappingFunction(v)
		end
		return result
	end
end

function p.merge(tbl, ...)
	if tbl == nil then
		return nil
	end
	for _, source in ipairs({...}) do
		for k, v in pairs(source) do
			if type(v) == "table" and type(tbl[k]) == "table" then
				tbl[k] = p.merge({}, tbl[k], v)
			else
				tbl[k] = p.clone(v)
			end
		end
	end
	return tbl
end

local inspect
local MAX_SINGLELINE = 50 -- If changing this, also change the variable of the same name at [[Module:UtilsTable/Documentation/Data]] 
function p.print(tbl, singleLine)
	inspect = inspect or require("Module:UtilsTable/Inspect") -- lazy-loaded for performance optimization
	return inspect(tbl, {
		multiline = function(t)
			if singleLine then
				return false
			end
			local size = 0
			for key, val in pairs(t) do
				if type(val) == "table" then
					return true
				end
				size = size + 1
			end
			local singleLineLength = #inspect(t, { multiline = false })
			return singleLineLength > MAX_SINGLELINE or size > #t and size - #t > 1
		end
	})
end

function p.printPath(pathComponents)
	local path = ""
	for _, pathComponent in pairs(pathComponents or {}) do
		if string.match(pathComponent, "^[A-Za-z_][A-Za-z_0-9]*$") then
			path = path .. "." .. pathComponent
		elseif string.match(pathComponent, "^%[.*%]$") then
			path = path .. pathComponent
		else
			path = path .. "[" .. p.print(pathComponent) .. "]"
		end
	end
	return path
end

function p.property(tbl, path)
	return p._property(path)(tbl)
end
function p._property(path)
	return function(tbl)
		if type(path) ~= "table" then
			path = { path }
		end
		local result = tbl
		for i, key in ipairs(path) do
			result = result[key] or result[mw.text.trim(key, '%[%]"')]
			if result == nil then
				return result
			end
		end
		return result
	end
end

function p.size(tbl)
	return #p.keys(tbl)
end

function p.stringKeys(tbl)
	local result = {}
	for k in pairs(tbl) do
		if type(k) == "string" then
			table.insert(result, k)
		end
	end
	return result
end

function p.toArray(tbl, keys, padValue)
	return p._toArray(keys, padValue)(tbl)
end
function p._toArray(keys, padValue)
	return function(tbl)
		local array = {}
		if keys then
			for i, key in ipairs(keys) do
				array[i] = tbl[key] or padValue
			end
		else
			for k, v in pairs(tbl) do
				table.insert(array, v)
			end
		end
		return array
	end
end

--[[
	"Array" functions (using the `ipairs` iterator, mostly)
--]]

function p.compact(array)
	local result = {}
	local j = 1
	for i = 1, table.maxn(array) do
		if array[i] then
			result[j] = array[i]
			j = j + 1
		end
	end
	return result
end

function p.concat(array, ...)
	if type(array) ~= "table" then
		array = {array}
	end
	local result = p.clone(array)
	for i, arrayOrValue in ipairs({...}) do
		if not p.hasArray(arrayOrValue) then
			h.append(result, arrayOrValue)
		else
			for _, value in ipairs(arrayOrValue) do
				h.append(result, value)
			end
		end
	end
	return result
end

function p.difference(array, other)
	local result = {}
	local lookup = p.invert(other)
	for i, v in ipairs(array) do
		if not lookup[v] then
			table.insert(result, v)
		end
	end
	return result
end

function p.dropWhile(array, predicate)
	return p._dropWhile(predicate)(array) 
end
function p._dropWhile(predicate)
	local predicate = h.predicate(predicate)
	return function(array)
		local i = 1
		while i <= #array and predicate(array[i], i) do
			i = i + 1
		end
		return p.slice(array, i)
	end
end

function p.dropRightWhile(array, predicate)
	return p._dropRightWhile(predicate)(array)
end
function p._dropRightWhile(predicate)
	local predicate = h.predicate(predicate)
	return function(array)
		local result = {}
		local i = p.len(array)
		while i > 0 and predicate(array[i], i) do
			i = i - 1
		end
		while i > 0 do
			table.insert(result, 1, array[i])
			i = i - 1
		end
		return result
	end
end

function p.filter(array, iteratee)
	return p._filter(iteratee)(array)
end
function p._filter(iteratee)
	return function(array)
		local predicateFn = h.predicate(iteratee)
		local results = {}
		for i, v in ipairs(array) do
			if predicateFn(v) then
				table.insert(results, v)
			end
		end
		return results
	end
end

function p.find(array, iteratee)
	return p._find(iteratee)(array)
end
function p._find(iteratee)
	local predicate = h.predicate(iteratee)
	return function(array)
		for i, v in ipairs(array) do
			if predicate(v) then
				return v, i
			end
		end
		return nil, nil
	end
end

function p.findIndex(array, iteratee)
	local index = select(2, p.find(array, iteratee))
	return index
end

function p.findLast(array, iteratee)
	return p._findLast(iteratee)(array)
end
function p._findLast(iteratee)
	local predicate = h.predicate(iteratee)
	return function(array)
		local v, i = p.find(p.reverse(array), predicate)
		if not i then
			return nil, nil
		end
		return v, p.len(array) - i + 1
	end
end

function p.flatten(array)
	local result = {}
	for _, v in ipairs(array) do
		result = p.concat(result, v)
	end
	return result
end

function p.flatMap(array, mappingFunction)
	return p._flatMap(mappingFunction)(array)
end
function p._flatMap(mappingFunction)
	return function(array)
		return p.flatten(p.map(array, mappingFunction))
	end
end

function p.fromPairs(pairs)
	local result = {}
	for i, pair in ipairs(pairs) do
		result[pair[1]] = pair[2]
	end
	return result
end

function p.groupBy(array, iteratee)
	return p._groupBy(iteratee)(array)
end
function p._groupBy(iteratee)
	local mappingFn = h.mapper(iteratee)
	return function(array)
		local result = {}
		for _, v in ipairs(array) do
			local groupingKey = mappingFn(v)
			if groupingKey then
				local group = result[groupingKey] or {}
				result[groupingKey] = p.concat(group, v)
			end
		end
		return result
	end
end

function p.includes(array, value)
	for _, v in ipairs(array) do
		if v == value then
			return true
		end
	end
	return false
end

function p.intersection(array, other)
	local result = {}
	for i, v in ipairs(array) do
		if p.keyOf(other, v) then
			table.insert(result, v)
		end
	end
	return result
end

function p.keyBy(array, iteratee)
	return p._keyBy(iteratee)(array)
end
function p._keyBy(iteratee)
	local mapper = h.mapper(iteratee)
	return function(array)
		local result = {}
		for i, v in ipairs(array) do
			result[mapper(v)] = v
		end
		return result
	end
end

function p.len(array)
	return #p.clone(array)
end

function p.map(array, iteratee)
	return p._map(iteratee)(array)
end
function p._map(iteratee)
	return function(array)
		local mappingFunction = iteratee
		if type(iteratee) == "string" then
			mappingFunction = function(val) return val[iteratee] end
		end
		local tbl2 = {}
		for k, v in ipairs(array) do
			tbl2[k] = mappingFunction(v)
		end
		return tbl2
	end
end

function p.min(array)
	local min = array[1]
	for _, v in ipairs(array) do
		min = math.min(min, v)
	end
	return min
end

function p.max(array)
	local max = array[1]
	for _, v in ipairs(array) do
		max = math.max(max, v)
	end
	return max
end

function p.padNils(array, padValue, max)
	return p._padNils(padValue, max)(array)
end
function p._padNils(padValue, max)
	return function(array)
		padValue = padValue or ''
		max = max or table.maxn(array)
		local result = p.clone(array)
		for i = 1, max do
			if result[i] == nil then
				result[i] = padValue
			end
		end
		return result
	end
end

function p.partition(array, iteratee)
	return p._partition(iteratee)(array)
end
function p._partition(iteratee)
	return function(array)
		local predicateFn = h.predicate(iteratee)
		local trueResults = {}
		local falseResults = {}
		for i, v in ipairs(array) do
			if predicateFn(v) then
				table.insert(trueResults, v)
			else
				table.insert(falseResults, v)
			end
		end
		return trueResults, falseResults
	end
end

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

function p.slice(array, s, e)
	return p._slice(s, e)(array)
end
function p._slice(s, e)
	return function(array)
		local tbl2 = {}
		e = e or p.len(array)
		local j = 1
		for i = s, e do
			tbl2[j] = array[i]
			i = i + 1
			j = j + 1
		end
		return tbl2
	end
end

function p.sortBy(array, iteratees)
	return p._sortBy(iteratees)(array)
end
function p._sortBy(iteratees)
	if type(iteratees) ~= "table" then
		iteratees = {iteratees}
	end
	local comparators = {}
	for i, iteratee in ipairs(iteratees) do
		local mappingFn = h.mapper(iteratee)
		comparators[i] = h.comparator(mappingFn)
	end
	
	return function(array)
		local result = p.clone(array)
		table.sort(result, function(a, b)
			local isEqual, isLessThan
			local i = 1
			repeat
				isEqual, isLessThan = comparators[i](a, b)
				i = i + 1
			until not isEqual or i > #iteratees
			return isLessThan
		end)
		return result
	end
end
function h.comparator(mappingFn)
	return function(a, b)
		a = mappingFn(a)
		b = mappingFn(b)
		return a == b, a < b
	end
end

function p.tail(array)
	local result = {}
	for i in ipairs(array) do
		if i > 1 then
			result[i - 1] = array[i]
		end
	end
	return result
end

function p.take(array, n)
	return p._take(n)(array)
end
function p._take(n)
	return function(array)
		return p.slice(array, 1, n)
	end
end

function p.takeWhile(array, predicate)
	return p._takeWhile(predicate)(array)
end
function p._takeWhile(predicate)
	local predicate = h.predicate(predicate)
	return function(array)
		local result = {}
		local i = 1
		while i <= p.len(array) and predicate(array[i], i) do
			result[i] = array[i]
			i = i + 1
		end
		return result 
	end
end

function p.union(arrays)
	local result = {}
	local seen = {}
	for _, array in ipairs(arrays) do
		for _, value in ipairs(array) do
			if not seen[value] then
				table.insert(result, value)
				seen[value] = true
			end
		end
	end
	return result
end

function p.unique(array)
	local result = {}
	for _, v in ipairs(array) do
		if not p.find(result, p._isEqual(v)) then
			table.insert(result, v)
		end
	end
	return result
end

function p.uniqueBy(array, iteratee)
	return p._uniqueBy(iteratee)(array)
end
function p._uniqueBy(iteratee)
	local mapper = h.mapper(iteratee)
	return function(array)
		local result = {}
		for _, v in ipairs(array) do
			local match = p.find(result, function(val)
				return mapper(val) == mapper(v)
			end)
			if not match then
				table.insert(result, v)
			end
		end
		return result
	end
end

-- Based on https://github.com/lua-stdlib/functional
-- See https://lua-stdlib.github.io/lua-stdlib/modules/std.functional.html#zip
function p.zip(array, padValue)
	local result = {}
	local len = p.len(array)
	for outerk, innerTbl in ipairs(array) do
		innerTbl = p.padNils(innerTbl, "NIL") -- to properly handle sparse arrays
		for k, v in ipairs(innerTbl) do
			result[k] = result[k] or {}
			if v ~= "NIL" then
				result[k][outerk] = v
			end
		end
		if padValue then
			for k in ipairs(result) do
				result[k] = p.padNils(result[k], padValue, len)
			end
		end
	end
	return result
end

p.Schemas = function() return {
	print = {
		singleLine = {
			type = "boolean",
		}
	},
	padNils = {
		padValue = {
			type = "any",
			default = '""',
		},
		max = {
			type = "number",
			default = "table.maxn(array)",
		},
	},
	slice = {
		["start"] = {
			type = "number",
			required = true,
		},
		["end"] = {
			type = "number",
			default = "#array",
		},
	},
	toArray = {
		keys = {
			type = "array",
			items = {
				oneOf = {
					{ type = "string" },
					{ type = "number" },
				},
			},
		},
		padValue = { type = "any" },
	},
	union = {
		arrays = {
			required = true,
			type = "array",
			items = {
				type = "array",
				items = {
					type = "any",
				},
			},
		},
	},
	zip = {
		arrays = {
			type = "array",
			required = true,
			items = { type = "any" },
		},
		padValue = {
			type = "any",
		},
	},
}
end

p.Documentation = function() 
	local propertyShorthand = "<code>{{Sect|property}}</code> shorthand"
	local isMatchShorthand = "<code>{{Sect|isMatch}}</code> shorthand"
	return {
		sections = {
			{
				heading = "Tables",
				section = {
					clone = {
						params = {"tbl"},
						returns = "Creates a shallow clone of <code>tbl</code>.",
						cases = {
							{
								snippet = 1,
								expect = {
									{ foo = {} },
									true, 
									true
								},
							},
						},
					},
					cloneDeep = {
						desc = "Similar to {{Scribunto Manual|lib=mw.clone}} except that it differs in how it handles metatables.",
						params = {"tbl"},
						returns = "Creates a recursive clone of <code>tbl</code>.",
						cases = {
							{
								snippet = 1,
								expect = {
									{ foo = {} },
									true,
									true,
								},
							},
						},
					},
					hasArray = {
						params = {"tbl"},
						returns = "True if the table contains integer keys (or is empty).",
						cases = {
							{
								args = {{1, 2, 3}},
								expect = true,
							},
							{
								args = {{}},
								expect = true,
							},
							{
								args = {{foo = "bar"}},
								expect = false,
							},
							{
								args = {{foo = "bar", "baz"}},
								expect = true,
							},
						}
					},
					hasKey = {
						params = {"tbl", "key"},
						_params = {{"key"}, {"tbl"}},
						returns = "True if <code>tbl[key]</code> is not nil, else false.",
						cases = {
							{
								args = {{"foo", nil, "bar"}, 3},
								expect = true,
							},
							{
								args = {{foo = "bar", baz = "quux"}, "baz"},
								expect = true,
							},
							{
								args = {{"foo", "bar"}, 3},
								expect = false
							},
							{
								args = {{foo = "a", baz = "b"}, "quux"},
								expect = false,
							},
						},
					},
					isArray = {
						params = {"tbl"},
						returns = "True if the table contains '''only''' integer keys (or is empty).",
						cases = {
							{
								args = {{1, 2, 3}},
								expect = true,
							},
							{
								args = {{}},
								expect = true,
							},
							{
								args = {{nil, nil, "foo"}},
								expect = true,
							},
							{
								args = {{[10] = "foo"}},
								expect = true,
							},
							{
								args = {{foo = "bar"}},
								expect = false,
							},
							{
								args = {{foo = "bar", "baz"}},
								expect = false,
							},
						},
					},
					isEmpty = {
						params = {"tbl"},
						returns = "True if <code>tbl</code> has no keys whatsoever",
						cases = {
							{
								args = {{}},
								expect = true,
							},
							{
								args = {{ foo = "bar" }},
								expect = false,
							},
							{
								args = {{nil, "foo"}},
								expect = false,
							},
						}
					},
					isEqual = {
						params = {"tbl", "other"},
						_params = {{"tbl"}, {"other"}},
						returns = "<code>true</code> if <code>tbl</code> deep equals <code>other</code>.",
						cases = {
							{
								args = {
									{ foo = { bar = "baz" } }, 
									{ foo = { bar = "baz" } },
								},
								expect = true,
							},
							{
								args = {
									{ foo = { bar = "baz" } }, 
									{ foo = { bar = "quux" } },
								},
								expect = false,
							},
						}
					},
					invert = {
						params = {"tbl"},
						returns = "A table with the values of <code>tbl</code> as its keys, and vice-versa.",
						cases = {
							{
								args = {{"foo", "bar", baz = "quux"}},
								expect = {
									foo = 1,
									bar = 2,
									quux = "baz"
								},
							},
							{
								desc = "Values will be overwritten if <code>tbl</code> has duplicate values. Overwrite order is not guaranteeed.",
								args = {{ 
									Ganon = "Power", 
									Ganondorf = "Power",
									Link = "Courage",
									Zelda = "Wisdom",
								}},
								expect = {
									Power = "Ganondorf",
									Courage = "Link",
									Wisdom = "Zelda",
								},
							},
						},
					},
					isMatch = {
						desc = "Performs a partial deep comparison between <code>tbl</code> and <code>other</code> to determine if <code>tbl</code> contains equivalent values.",
						params = {"tbl", "source"},
						_params = {{"source"}, {"tbl"}},
						returns = "Returns <code>true</code> if <code>tbl</code> is a match, else false",
						cases = {
							{
								args = {
									{ foo = { bar = "baz", flip = "flop" } },
									{ foo = { bar = "baz" } },
								},
								expect = true,
							},
							{
								args = {
									{1, 2, 3},
									{1, 2},
								},
								expect = true,
							},
							{
								args = {
									{ foo = { bar = "baz" } },
									{ foo = { bar = "quux" } },
								},
								expect = false
							},
						},
					},
					keyOf = {
						params = {"tbl", "value"},
						returns = "First key found whose value is shallow-equal to <code>value</code>, or nil if none found.",
						cases = {
							outputOnly = true,
							{
								args = {{"foo", nil, "bar"}, "bar"},
								expect = 3,
							},
							{
								args = {{foo = "bar", baz = "quux"}, "quux"},
								expect = "baz",
							},
							{
								args = {{"foo", "bar"}, "quux"},
								expect = nil
							},
							{
								desc = "Does not perform deep-equal checks on tables.",
								args = {{{}, {}}, {}},
								expect = nil
							},
						},
					},
					keys = {
						desc = "See also {{Sect|values}} and {{Sect|stringKeys}}.",
						params = {"tbl"},
						returns = "Array of <code>tbl</code> keys.",
						cases = {
							{
								args = {{"foo", "bar", "baz"}},
								expect = {1, 2, 3},
							},
							{
								args = {{ baz = "quux", foo = "bar" }},
								expect = {"foo", "baz"},
							},
							{
								args = {{"foo", bar = "baz", nil, "quux"}},
								expect = {1, 3, "bar"}
							},
						},
					},
					mapValues = {
						params = {"tbl", "iteratee"},
						returns = "Creates a table with the same keys as <code>tbl</code> and values generated by running each value of <code>tbl</code> thru iteratee.",
						cases = {
							{
								snippet = 1,
								expect = { arg1 = "foo", arg2 = "bar"}
							},
							{
								desc = propertyShorthand,
								args = {
									{
										Link = {
											Triforce = "Courage",
										},
										Zelda = {
											Triforce = "Wisdom"
										},
									},
									"Triforce",
								},
								expect = {
									Link = "Courage",
									Zelda = "Wisdom",
								},
							},
						},
					},
					merge = {
						desc = "Recursively merges tables.",
						params = {"tbl", "..." },
						returns = "<code>tbl</code> with merged values. Subsequent sources overwrite key assignments of previous sources.",
						cases = {
							{
								snippet = 1,
								expect = {
									flib = "flob",
									foo = {
										bar = {"noot", "flob"},
										baz = "noot",
										wibble = "wobble",
									},
								}
							},
							{
								desc = "Common use: merging keys into new table.",
								args = {
									{}, 
									{ flib = "flob" }, 
									{ wibble = "wobble" },
								},
								expect = {
									flib = "flob",
									wibble = "wobble",
								},
							},
						}
					},
					print = {
						params = {"tbl", "singleLine"},
						returns = "<code>tbl</code> pretty-printed as a string.",
						cases = {
							outputOnly = true,
							{
								desc = "Prints array items on a single line.",
								args = {{"foo", "bar", "baz"}},
								expect = '{"foo", "bar", "baz"}',
							},
							{
								desc = "Prints single line when tables has one string key.",
								args = {{ foo = "bar" }},
								expect = '{ foo = "bar" }',
							},
							{
								args = {{1, 2, 3, foo = "bar" }},
								expect = '{1, 2, 3, foo = "bar"}',
							},
							{
								desc = "Prints one value per line if more than one string key.",
								args = {{ foo = "bar", flib = "flub" }},
								expect = [[{
								  flib = "flub",
								  foo = "bar",
								}]],
							},
							{
								args = {{1, 2, 3, foo = "bar", flib = "flub" }},
								expect = [[{
								  1,
								  2,
								  3,
								  flib = "flub",
								  foo = "bar",
								}]]
							},
							{
								desc = "Prints one value per line if any are tables.",
								args = {{{1}, {2}}},
								expect = [[{
								  {1},
								  {2},
								}]],
							},
							{
								desc = string.format("Prints one value per line if single-line would exceed %s characters.", MAX_SINGLELINE),
								args = {{"abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}},
								expect = [[{
								  "abcdefghijklmnopqrstuvwxyz",
								  "abcdefghijklmnopqrstuvwxyz",
								}]]
							},
							{
								desc = "Always prints single-line when <code>singleLine</code> is true",
								args = {{"abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}, true},
								expect = '{"abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}'
							},
						},
					},
					printPath = {
						params = {"path"},
						returns = "Property path as a string.",
						cases = {
							outputOnly = true,
							{
								args = {{"foo", 1, "bar", 1}},
								expect = ".foo[1].bar[1]",
							},
							{
								args = {{"foo", '["bar"]'}},
								expect = '.foo["bar"]',
							},
						},
					},
					property = {
						params = {"tbl", "path"},
						_params = {{"path"}, {"tbl"}},
						returns = "The value at <code>path</code> for <code>tbl</code>.",
						cases = {
							outputOnly = true,
							{
								args = {{ foo = {"bar"} }, {"foo", 1}},
								expect = "bar",
							},
							{
								args = {{ foo = {"bar"} }, {"foo", "bar", "baz"}},
								expect = nil,
							},
						},
					},
					size = {
						params = {"tbl"},
						returns = "Total number of keys in <code>tbl</code>.",
						cases = {
							{
								args = {{1, 2, foo = "bar"}},
								expect = 3,
							},
						},
					},
					stringKeys = {
						params = {"tbl"},
						returns = "Array of string keys in <code>tbl</code>",
						cases = {
							{
								args = {{1, 2, foo = "bar", [true] = false}},
								expect = {"foo"},
							},
						},
					},
					ivalues = {
						params = {"tbl"},
						returns = "Array of contiguous, integer-keyed values in <code>tbl</code> starting from 1.",
						cases = {
							{
								args = {{"foo", "bar", wibble = "wobble", [10] = "baz"}},
								expect = {"foo", "bar"},
							},
						},
					},
					toArray = {
						params = {"tbl", "keys", "padValue"},
						_params = {{"keys", "padValue"}, {"tbl"}},
						returns = "An array of all the values in <code>tbl</code>. Order not guaranteed unless <code>keys</code> is specified. If so, the returned array is such that <code>array[i] = utilsTable.keyOf(keys, tbl[i])</code>. Note that the function will return a sparse array when <code>tbl[i] == nil</code>.",
						cases = {
							{
								desc = "Order not guaranteed.",
								args = {
									{ a = "foo", b = 2, c = true },
								},
								expect = {"foo", true, 2},
							},
							{
								desc = "<code>keys</code> param can be used to specify order.",
								args = {
									{ a = "foo", b = 2, c = true },
									{"c", "a", "b"},
								},
								expect = {true, "foo", 2},
							},
							{
								desc = "<code>keys</code> param can be used to grab a subset of the keys.",
								args = {
									{ a = "foo", b = 2, c = true },
									{"a", "b"},
								},
								expect = {"foo", 2},
							},
							{
								desc = "<code>keys</code> param can result in a sparse array if key not in <code>tbl</code>.",
								args = {
									{ a = "foo", b = 2, c = true },
									{"b", "a", "d", "c"},
								},
								expect = {2, "foo", [4] = true},
							},
							{
								desc = "Sparse arrays can be padded with a custom <code>padValue</code>.",
								args = {
									{ a = "foo", b = 2, c = true },
									{"b", "a", "d", "c"},
									""
								},
								expect = {2, "foo", "", true},
							},
						},
					},
				},
			},
			{
				heading = "Arrays",
				section = {
					compact = {
						params = {"array"},
						returns = "Creates an array with falsey values removed.",
						cases = {
							{
								args = {{0, false, 1, ""}},
								expect = {0, 1, ""}
							},
						},
					},
					concat = {
						params = {"array", "..."},
						returns = "Creates a new array concatenating array with any additional arrays and/or values.",
						cases = {
							{
								snippet = 1,
								expect = {1, 2, 3, 4, {5}, 6},
							},
							{
								desc = "Tables with only string keys are treated as single values.",
								args = {{}, {1, 2}, {3, 4, foo = "bar"}, { foo = "quux" }},
								expect = {1, 2, 3, 4, { foo = "quux" }},
							},
						},
					},
					difference = {
						params = {"array", "other"},
						returns = "An array of all the elements in <code>array</code> that are not in <code>other</code>.",
						cases = {
							{
								args = {{"a", "b", "c"}, {"c", "d"}},
								expect = {"a", "b"},
							},
							{
								desc = "Does not deep-compare.",
								args = {{{ foo = "bar" }}, {{ foo = "bar" }}},
								expect = {{ foo = "bar" }},
							}
						},
					},
					dropWhile = {
						params = {"array", "predicate"},
						_params = {{"predicate"}, {"array"}},
						returns = "Creates a slice of <code>array</code> excluding elements dropped from the beginning. Elements are dropped until <code>predicate</code> returns falsey.",
						cases = {
							{
								snippet = 1,
								expect = {"ALttP", "LA", "OoT"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "SS", hasMasterSword = true },
										{ game = "ALBW", hasMasterSword = true },
										{ game = "TFH", hasMasterSword = false },
										{ game = "BotW", hasMasterSword = true },
									},
									"hasMasterSword",
								},
								expect = {
									{ game = "TFH", hasMasterSword = false },
									{ game = "BotW", hasMasterSword = true },
								},
							},
							{
								snippet = 2,
								expect = {},
							},
						},
					},
					dropRightWhile = {
						params = {"array", "predicate"},
						_params = {{"predicate"}, {"array"}},
						returns = "Creates a slice of <code>array</code> excluding elements dropped from the end. Elements are dropped until <code>predicate</code> returns falsey.",
						cases = {
							{
								snippet = 1,
								expect = {"...", "SS", "ALBW"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "SS", hasMasterSword = true },
										{ game = "ALBW", hasMasterSword = true },
										{ game = "TFH", hasMasterSword = false },
										{ game = "BotW", hasMasterSword = true },
									},
									"hasMasterSword",
								},
								expect = {
									{ game = "SS", hasMasterSword = true },
									{ game = "ALBW", hasMasterSword = true },
									{ game = "TFH", hasMasterSword = false },
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ game = "SS", system = "console" },
										{ game = "ALBW", system = "handheld" },
										{ game = "TFH", system = "handheld" },
										{ game = "BotW", system = "console" },
									},
									{ system = "console" },
								},
								expect = {
									{ game = "SS", system = "console" },
									{ game = "ALBW", system = "handheld" },
									{ game = "TFH", system = "handheld" },
								},
							},
						},
					},
					keyBy = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "Creates a table composed of keys generated from the results of running each element of <code>array</code> thru <code>iteratee</code>",
						cases = {
							{
								snippet = 1,
								expect = {
									["TWW Link"] = {
										name = "Link",
										game = "TWW",
										age = 10,
									},
									["TP Link"] = {
										name = "Link",
										game = "TP",
										age = 17,
									},
								},
							},
							{
								desc = propertyShorthand,
								args = {{
									{
										name = "Link",
										age = 10,
									},
									{
										name = "Zelda",
										age = 10,
									},
									{
										name = "Zelda",
										age = 17,
									},
								}, "name"},
								expect = {
									["Link"] = {
										name = "Link",
										age = 10
									},
									["Zelda"] = {
										name = "Zelda",
										age = 17,
									},
								}
							},
						},
					},
					filter = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "Iterates over array elements in <code>array</code>, returning an array of all elements <code>iteratee</code> returns truthy for.",
						cases = {
							{
								snippet = 1,
								expect = {"foo", "bar"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "The Wind Waker", canon = true },
										{ game = "Twilight Princess", canon = true },
										{ game = "Tingle's Rosy Rupeeland", canon = false },
									},
									"canon",
								},
								expect = {
									{ game = "The Wind Waker", canon = true },
									{ game = "Twilight Princess", canon = true },
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ game = "The Wind Waker", type = "main" },
										{ game = "Twilight Princess", type = "main" },
										{ game = "Tingle's Rosy Rupeeland", type = "spinoff" },
									},
									{ type = "main" },
								},
								expect = {
									{ game = "The Wind Waker", type = "main" },
									{ game = "Twilight Princess", type = "main" },
								},
							},
						},
					},
					find = {
						params = {"tbl", "iteratee"},
						_params = {{"iteratee"}, {"tbl"}},
						returns = {"The value if found, else <code>nil</code>", "The index of the value found, else <code>nil</code>"},
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = {"bar", 2}
							},
							{
								snippet = 2,
								expect = {nil, nil},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "Tingle's Rosy Rupeeland", canon = false },
										{ game = "The Wind Waker", canon = true },
										{ game = "Breath of the Wild", canon = true },
									},
									"canon"
								},
								expect = {
									{ game = "The Wind Waker", canon = true },
									2,
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ 
											game = "Tingle's Rosy Rupeeland", 
											canon = false,
											type = "spinoff",
										},
										{
											game = "Twilight Princess HD",
											canon = true,
											type = "remake",
										},
										{ 
											game = "Breath of the Wild", 
											canon = true,
											type = "main" 
										},
									},
									{ canon = true, type = "main" }
								},
								expect = {
									{ 
										game = "Breath of the Wild", 
										canon = true,
										type = "main" 
									},
									3
								}
							}
						}
					},
					findIndex = {
						params = {"tbl", "iteratee"},
						returns = "The index of the value if found, else <code>nil</code>",
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = 2
							},
							{
								snippet = 2,
								expect = nil,
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "Tingle's Rosy Rupeeland", canon = false },
										{ game = "The Wind Waker", canon = true },
										{ game = "Breath of the Wild", canon = true },
									},
									"canon"
								},
								expect = 2,
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ 
											game = "Tingle's Rosy Rupeeland", 
											canon = false,
											type = "spinoff",
										},
										{
											game = "Twilight Princess HD",
											canon = true,
											type = "remake",
										},
										{ 
											game = "Breath of the Wild", 
											canon = true,
											type = "main" 
										},
									},
									{ canon = true, type = "main" }
								},
								expect = 3
							}
						},
					},
					findLast = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = {
							"The last value found matching <code>iteratee</code>, else <code>nil</code>.", 
							"The index of the value, else <code>nil</code>."
						},
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = {"baz", 3},
							},
							{
								snippet = 2,
								expect = {nil, nil},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "Tingle's Rosy Rupeeland", canon = false },
										{ game = "The Wind Waker", canon = true },
										{ game = "Breath of the Wild", canon = true },
									},
									"canon"
								},
								expect = {
									{ game = "Breath of the Wild", canon = true },
									3,
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ 
											game = "Tingle's Rosy Rupeeland", 
											canon = false,
											type = "spinoff",
										},
										{
											game = "Twilight Princess",
											canon = true,
											type = "main",
										},
										{ 
											game = "Breath of the Wild", 
											canon = true,
											type = "main" 
										},
									},
									{ canon = true, type = "main" }
								},
								expect = {
									{ 
										game = "Breath of the Wild", 
										canon = true,
										type = "main" 
									},
									3,
								},
							},
						},
					},
					flatten = {
						params = {"array"},
						returns = "Returns <code>array</code> but flattened a single level deep.",
						cases = {
							{
								args = {{1, {2, {3, 4}}, 5}},
								expect = {1, 2, {3, 4}, 5}
							},
						},
					},
					flatMap = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "A flattened array of values created by running each element in <code>array</code> thru <code>iteratee</code> and flattening the mapped results.",
						cases = {
							{
								snippet = 1,
								expect = {1, 1, 2, 2},
							},
						},
					},
					fromPairs = {
						params = {"pairs"},
						returns = "An object composed from key-value <code>pairs</code>.",
						cases = {
							{
								args = {
									{
										{"a", 1},
										{"b", 2},
									},
								},
								expect = {
									a = 1,
									b = 2,
								},
							},
						},
					},
					groupBy = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "A table composed of keys generated from the results of running each element of <code>array</code> thru <code>iteratee</code>. The order of grouped values is determined by the order they occur in <code>array</code>. The corresponding value of each key is an array of elements responsible for generating the key. If a <code>nil</code> key is generated for a given value, that value will be absent from the resulting table.",
						cases = {
							{
								snippet = 1,
								expect = {
									[6] = {6.1, 6.3},
									[4] = {4.2},
								},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{
											page = "Link",
											term = "Hero of Time",
											game = "OoT",
										},
										{
											page = "Link",
											term = "Hero of Winds",
											game = "TWW"
										},
										{
											page = "Princess Zelda",
											term = "Zelda",
											game = "SS",
										},
										{
											someOtherData = "foo",
										},
									},
									"page",
								},
								expect = {
									["Link"] = {
										{
											page = "Link",
											term = "Hero of Time",
											game = "OoT",
										},
										{
											page = "Link",
											term = "Hero of Winds",
											game = "TWW"
										},
									},
									["Princess Zelda"] = {
										{
											page = "Princess Zelda",
											term = "Zelda",
											game = "SS",
										},
									},
								},
							},
						},
					},
					includes = {
						params = {"array", "value"},
						returns = "True if and only if <code>value</code> is in <code>array</code>.",
						cases = {
							{
								args = {{"foo", "bar"}, "foo"},
								expect = true
							},
							{
								args = {{"foo", "bar"}, "baz"},
								expect = false
							},
						},
					},
					intersection = {
						params = {"array", "other"},
						returns = "An array of all the elements that are in both <code>array</code> and <code>other</code>",
						cases = {
							{
								args = {{"a", "b", "c"}, {"b"}},
								expect = {"b"},
							},
							{
								desc = "Does not deep-compare.",
								args = {{{ foo = "bar" }}, {{ foo = "bar" }}},
								expect = {},
							},
						},
					},
					len = {
						params = {"array"},
						returns = "The length of the array. Works with {{Scribunto Manual|frame.args}} and tables loaded thru {{Scribunto Manual|mw.loadData}}.",
						cases = {
							{
								args = {{1, 2, 3, [10] = 10}},
								expect = 3,
							},
						},
					},
					map = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "Creates an array of values by running each array element in <code>array</code> thru <code>iteratee</code>.",
						cases = {
							{
								snippet = 1,
								expect = {"true", "false"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{
											name = "Link",
											triforce = "Courage",
										},
										{
											name = "Zelda",
											triforce = "Wisdom",
										},
										{
											name = "Ganon",
											triforce = "Power"
										},
									},
									"triforce"
								},
								expect = {"Courage", "Wisdom", "Power"},
							},
						},
					},
					min = {
						params = {"array"},
						returns = "The maximum value of <code>array</code>, or nil if empty.",
						cases = {
							{
								args = {{3, 2, 1}},
								expect = 1,
							},
							{
								args = {{}},
								expect = nil,
							},
						},
					},
					max = {
						params = {"array"},
						returns = "The maximum value of <code>array</code>, or nil if empty.",
						cases = {
							{
								args = {{5, 10, 20}},
								expect = 20,
							},
							{
								args = {{}},
								expect = nil,
							},
						},
					},
					padNils = {
						params = {"array", "padValue", "max"},
						_params = {{"padValue", "max"}, {"array"}},
						returns = "Returns a version of <code>array</code> such that nil-valued indices up to and including <code>max</code> are replaced with <code>padValue</code>.",
						cases = {
							{
								args = {{nil, 2, nil, 4}, 0},
								expect = {0, 2, 0, 4},
							},
							{
								args = {{nil, 2, nil, 4}, 0, 1},
								expect = {0, 2, nil, 4},
							},
							{
								args = {{nil, 2, nil, 4}, 0, 6},
								expect = {0, 2, 0, 4, 0, 0},
							},
							{
								args = {{"foo", nil, "baz"}},
								expect = {"foo", "", "baz"},
							},
						},
					},
					partition = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = {
							"<code>array</code> elements that <code>iteratee</code> returns truthy for.",
							"<code>array</code> elements that <code>iteratee</code> returns falsey for.",
						},
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = {
									{"foo", "quux"},
									{"bar", "baz"},
								},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "The Wind Waker", canon = true },
										{ game = "Twilight Princess", canon = true },
										{ game = "Tingle's Rosy Rupeeland", canon = false },
									},
									"canon",
								},
								expect = {
									{
										{ game = "The Wind Waker", canon = true },
										{ game = "Twilight Princess", canon = true },
									},
									{
										{ game = "Tingle's Rosy Rupeeland", canon = false },
									}
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ game = "The Wind Waker", type = "main" },
										{ game = "Twilight Princess", type = "main" },
										{ game = "Tingle's Rosy Rupeeland", type = "spinoff" },
									},
									{ type = "main" },
								},
								expect = {
									{
										{ game = "The Wind Waker", type = "main" },
										{ game = "Twilight Princess", type = "main" },
									},
									{
										{ game = "Tingle's Rosy Rupeeland", type = "spinoff" },
									},
								},
							},
						},
					},
					reverse = {
						params = {"array"},
						returns = "Reverses <code>array</code> so that the first element becomes the last, the second element becomes the second to last, and so on.",
						cases = {
							{
								args = {{1, 2, 3}},
								expect = {3, 2, 1},
							},
							{
								desc = "Ignores non-consecutive integer keys",
								args = {{1, 2, 3, [100] = 100}},
								expect = {3, 2, 1},
							},
						},
					},
					slice = {
						params = {"array", "start", "end"},
						_params = {{"start", "end"}, {"array"}},
						returns = "Creates a slice of <code>array</code> from <code>start</code> up to and including <code>end</code>.",
						cases = {
							{
								args = {{"a", "b", "c"}, 1, 2},
								expect = {"a", "b"},
							},
							{
								args = {{"a", "b", "c"}, 2, nil},
								expect = {"b", "c"},
							},
						}
					},
					sortBy = {
						params = {"array", "iteratees"},
						_params = {{"iteratees"}, {"array"}},
						returns = "An array of elements, sorted in ascending order by the results of running each element in <code>array</code> thru each iteratee. This method performs an <u>unstable</u> sort, that is, it does not guarantee that the original order of equal elements will be preserved.",
						cases = {
							{
								snippet = 1,
								expect = {
									{
										game = "TWW",
										systems = {"GCN", "Wii U"},
									},
									{
										game = "LA",
										systems = {"GB", "GBC", "3DS VC"}
									},
									{
										game = "OoT",
										systems = {"N64", "GCN", "iQue", "Wii VC", "Wii U VC"},
									},
								},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{
											name = "Link",
											age = 10,
										},
										{
											name = "Zelda",
											age = 10
										},
										{
											name = "Zelda",
											age = 17
										},
										{
											name = "Link",
											age = 17
										},
									},
									"name",
								},
								expect = {
									{
										name = "Link",
										age = 10,
									},
									{
										name = "Link",
										age = 17,
									},
									{
										name = "Zelda",
										age = 17,
									},
									{
										name = "Zelda",
										age = 10,
									},
								},
							},
							{
								desc = "Multiple sort criteria",
								args = {
									{
										{
											name = "Link",
											age = 10,
										},
										{
											name = "Zelda",
											age = 10
										},
										{
											name = "Zelda",
											age = 17
										},
										{
											name = "Link",
											age = 17
										},
									},
									{"name", "age"},
								},
								expect = {
									{
										name = "Link",
										age = 10,
									},
									{
										name = "Link",
										age = 17,
									},
									{
										name = "Zelda",
										age = 10,
									},
									{
										name = "Zelda",
										age = 17,
									},
								},
							},
						},
					},
					tail = {
						params = {"array"},
						returns = "Gets all but the first element of <code>array</code>.",
						cases = {
							{
								args = {{1, 2, 3}},
								expect = {2, 3},
							},
							{
								args = {{}},
								expect = {},
							},
						}
					},
					take = {
						params = {"array", "n"},
						_params = {{"n"}, {"array"}},
						returns = "Creates a slice of array with n elements taken from the beginning.",
						cases = {
							{
								args = {{1, 2, 3}, 2},
								expect = {1, 2},
							},
							{
								args = {{1, 2, 3}, 5},
								expect = {1, 2, 3},
							},
							{
								args = {{1, 2, 3}, 0},
								expect = {},
							},
						},
					},
					takeWhile = {
						params = {"array", "predicate"},
						_params = {{"predicate"}, {"array"}},
						returns = "Creates a slice of <code>array</code> with elements taken from the beginning. Elements are taken until <code>predicate</code> returns falsey.",
						cases = {
							{
								snippet = 1,
								expect = {"TLoZ", "TAoL", "ALttP", "LA"},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ game = "TLoZ", is2D = true },
										{ game = "TAoL", is2D = true },
										{ game = "ALttP", is2D = true },
										{ game = "LA", is2D = true },
										{ game = "OoT", is2D = false },
										{ game = "TMC", is2D = true },
									},
									"is2D",
								},
								expect = {
									{ game = "TLoZ", is2D = true },
									{ game = "TAoL", is2D = true },
									{ game = "ALttP", is2D = true },
									{ game = "LA", is2D = true },
								},
							},
							{
								desc = isMatchShorthand,
								args = {
									{
										{ game = "TLoZ", system = "console" },
										{ game = "TAoL", system = "console" },
										{ game = "ALttP", system = "console" },
										{ game = "LA", system = "handheld" },
										{ game = "OoT", system = "console" },
									},
									{ system = "console" },
								},
								expect = {
									{ game = "TLoZ", system = "console" },
									{ game = "TAoL", system = "console" },
									{ game = "ALttP", system = "console" },
								},
							},
						},
					},
					union = {
						params = {"arrays"},
						returns = "An array of unique values, in order, from all given arrays.",
						cases = {
							{
								args = {{{"a", "b", "c"}, {"b"}, {"c", "d"}}},
								expect = {"a", "b", "c", "d"},
							},
							{
								desc = "Does not deep-compare for equality.",
								args = {
									{
										{
											{ foo = "bar" }, 
											{ foo = "bar" },
										},
									}
								},
								expect = {
									{ foo = "bar" },
									{ foo = "bar" },
								},
							},
						},
					},
					unique = {
						params = {"array"},
						returns = "A copy of <code>array</code> but without the duplicate values. Elements are deep-compared. he order of result values is determined by the order they occur in the array.",
						cases = {
							{
								args = {
									{1, 2, 2, {foo = "bar"}, {foo = "quux"}, {foo = "bar"}},
								},
								expect = {1, 2, {foo = "bar"}, {foo = "quux"}},
							},
						},
					},
					uniqueBy = {
						params = {"array", "iteratee"},
						_params = {{"iteratee"}, {"array"}},
						returns = "A copy of <code>array</code> but without the duplicate values. <code>iteratee</code> is invoked for each element in array to generate the criterion by which uniqueness is computed.",
						cases = {
							{
								snippet = 1,
								expect = {
									{ title = "LA", game = "LA" },
									{ title = "OoT", game = "OoT" },
								},
							},
							{
								desc = propertyShorthand,
								args = {
									{
										{ title = "LA", game = "LA" },
										{ title = "OoT", game = "OoT" },
										{ title = "LADX", game = "LA" },
										{ title = "OoT3D", game = "OoT" },
										{ title = "LANS", game = "LA" },
									},
									"game"
								},
								expect = {
									{ title = "LA", game = "LA" },
									{ title = "OoT", game = "OoT" },
								},
							},
						},
					},
					zip = {
						params = {"arrays", "padValue"},
						returns = [[
							Creates a transposition of <code>arrays</code>. That is, an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on.
							Should the elements of <code>arrays</code> not be of the same length, the resulting groups can be padded to the same length with <code>padValue</code>.
						]],
						cases = {
							{
								args = {{
									{1, 2},
									{"a", "b"},
									{true, false},
								}},
								expect = {
									{1, "a", true},
									{2, "b", false},
								},
							},
							{
								args = {{
									{1, 2},
									{"a", "b", "c"},
									{true}
								}, ""},
								expect = {
									{1, "a", true},
									{2, "b", ""},
									{"", "c", ""},
								},
							},
							{
								args = {{
									{1, 2},
									{"a", "b", "c"},
									{true}
								}},
								expect = {
									{1, "a", true},
									{2, "b", nil},
									{nil, "c", nil},
								}
							}
						},
					},
				},
			},
		},
	}
end

return p