<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://petitplanet.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ATableTools</id>
	<title>Module:TableTools - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://petitplanet.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3ATableTools"/>
	<link rel="alternate" type="text/html" href="https://petitplanet.wiki/index.php?title=Module:TableTools&amp;action=history"/>
	<updated>2026-04-13T06:25:02Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://petitplanet.wiki/index.php?title=Module:TableTools&amp;diff=13&amp;oldid=prev</id>
		<title>Stevium: Created Module:TableTools</title>
		<link rel="alternate" type="text/html" href="https://petitplanet.wiki/index.php?title=Module:TableTools&amp;diff=13&amp;oldid=prev"/>
		<updated>2025-11-09T08:25:29Z</updated>

		<summary type="html">&lt;p&gt;Created Module:TableTools&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- &amp;lt;nowiki&amp;gt;&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Source: https://genshin-impact.fandom.com/wiki/Module:TableTools&lt;br /&gt;
-- This module includes a number of functions for dealing with Lua tables.&lt;br /&gt;
--&lt;br /&gt;
-- @script TableTools&lt;br /&gt;
-- @alias p&lt;br /&gt;
-- @release stable&lt;br /&gt;
-- @require [[mw:Extension:Scribunto/Lua_reference_manual#libraryUtil|libraryUtil]]&lt;br /&gt;
-- @attribution [[wikipedia:Module:TableTools|Module:TableTools]] (Wikipedia)&lt;br /&gt;
-- @see [[Wikipedia:Module:TableTools]] for a similar module.&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
local p = {}&lt;br /&gt;
local libraryUtil = require(&amp;#039;libraryUtil&amp;#039;)&lt;br /&gt;
 &lt;br /&gt;
-- Define often-used variables and functions.&lt;br /&gt;
local floor = math.floor&lt;br /&gt;
local infinity = math.huge&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Returns a new table with all parameters stored into keys 1, 2, etc. and with&lt;br /&gt;
-- a field `n` with the total number of parameters. Note that the resulting&lt;br /&gt;
-- table may not be a sequence.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.pack&lt;br /&gt;
-- @param[opt] ...&lt;br /&gt;
-- @return {table}&lt;br /&gt;
-- @see &amp;lt;http://www.lua.org/manual/5.2/manual.html#pdf-table.pack&amp;gt;&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.pack(...)&lt;br /&gt;
    return {n = select(&amp;#039;#&amp;#039;, ...), ...}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Returns the first `n` arguments in `...`. If `n` is negative, arguments are&lt;br /&gt;
-- counted from the end of the table.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.selectFirst&lt;br /&gt;
-- @param {number} n&lt;br /&gt;
-- @param[opt] ...&lt;br /&gt;
-- @see [[Lua reference manual/Standard libraries#select]]&lt;br /&gt;
-- @see &amp;lt;http://lua-users.org/wiki/VarargTheSecondClassCitizen&amp;gt;&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.selectFirst(n, ...)&lt;br /&gt;
    checkType(&amp;#039;Dev:TableTools.selectFirst&amp;#039;, 1, n, &amp;#039;number&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    local function err()&lt;br /&gt;
        error(&amp;#039;bad argument #1 to \&amp;#039;Dev:TableTools.selectFirst\&amp;#039; &amp;#039; ..&lt;br /&gt;
              &amp;#039;(index out of range)&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local function recurse(index, next, ...)&lt;br /&gt;
        if index == 0 then&lt;br /&gt;
            return&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        return next, recurse(index - 1, ...)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    n = math.modf(n)&lt;br /&gt;
&lt;br /&gt;
    local count = select(&amp;quot;#&amp;quot;, ...)&lt;br /&gt;
&lt;br /&gt;
    if -count &amp;gt; n then&lt;br /&gt;
        err()&lt;br /&gt;
    elseif -1 &amp;gt; n and n &amp;gt;= -count then&lt;br /&gt;
        return recurse(count + 1 + n, ...)&lt;br /&gt;
    elseif n == -1 then&lt;br /&gt;
        return ...&lt;br /&gt;
    elseif n == 0 then&lt;br /&gt;
        err()&lt;br /&gt;
    elseif n == 1 then&lt;br /&gt;
        return (...)&lt;br /&gt;
    elseif 1 &amp;lt; n and n &amp;lt;= count then&lt;br /&gt;
        return recurse(n, ...)&lt;br /&gt;
    elseif count &amp;lt; n then&lt;br /&gt;
        return ...&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Returns `true` if a given table is a sequence.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.isSequence&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @return {boolean}&lt;br /&gt;
-- @see &amp;lt;http://stackoverflow.com/a/6080274&amp;gt;&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.isSequence(t)&lt;br /&gt;
    checkType(&amp;#039;Dev:TableTools.isSequence&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    local i = 1&lt;br /&gt;
&lt;br /&gt;
    for _ in pairs(t) do&lt;br /&gt;
        if t[i] == nil then&lt;br /&gt;
            return false&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        i = i + 1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Returns the number of elements in a table, even if it is not a sequence.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.size&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @return {number}&lt;br /&gt;
-- @see &amp;lt;http://stackoverflow.com/a/2705804&amp;gt;&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.size(t)&lt;br /&gt;
    checkType(&amp;#039;Dev:TableTools.size&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    local i = 0&lt;br /&gt;
&lt;br /&gt;
    for _ in pairs(t) do&lt;br /&gt;
        i = i + 1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Returns `true` if a given table contains a certain element.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.includes&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @param elm&lt;br /&gt;
-- @return {boolean}&lt;br /&gt;
-- @see &amp;lt;http://stackoverflow.com/q/2282444&amp;gt;&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.includes(t, elm)&lt;br /&gt;
    checkType(&amp;#039;Dev:TableTools.includes&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    for _, v in pairs(t) do&lt;br /&gt;
        if v == elm then&lt;br /&gt;
            return true&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Merges the content of the second table with the content in the first one.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.merge&lt;br /&gt;
-- @param {table} dest&lt;br /&gt;
-- @param {table} source&lt;br /&gt;
-- @return {table}&lt;br /&gt;
-- @see &amp;lt;http://wiki.garrysmod.com/page/table/Merge&amp;gt;&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
function p.merge(dest, source)&lt;br /&gt;
    checkType(&amp;#039;Dev:TableTools.merge&amp;#039;, 1, dest, &amp;#039;table&amp;#039;)&lt;br /&gt;
    checkType(&amp;#039;Dev:TableTools.merge&amp;#039;, 2, source, &amp;#039;table&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    for k, v in pairs(source) do&lt;br /&gt;
        if type(v) == &amp;#039;table&amp;#039; and type(dest[k]) == &amp;#039;table&amp;#039; then&lt;br /&gt;
            -- Don&amp;#039;t overwrite one table with another; instead merge them&lt;br /&gt;
            -- recurisvely.&lt;br /&gt;
            p.merge(dest[k], v)&lt;br /&gt;
        else&lt;br /&gt;
            dest[k] = v&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return dest&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This function returns true if the given value is a positive integer, and false&lt;br /&gt;
-- if not. Although it doesn&amp;#039;t operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a given table key is in the array part or the&lt;br /&gt;
-- hash part of a table.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.isPositiveInteger&lt;br /&gt;
-- @param v&lt;br /&gt;
-- @return {boolean}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isPositiveInteger(v)&lt;br /&gt;
	if type(v) == &amp;#039;number&amp;#039; and v &amp;gt;= 1 and floor(v) == v and v &amp;lt; infinity then&lt;br /&gt;
		return true&lt;br /&gt;
	else&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This function returns true if the given number is a NaN value, and false&lt;br /&gt;
-- if not. Although it doesn&amp;#039;t operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a value can be a valid table key. Lua will&lt;br /&gt;
-- generate an error if a NaN is used as a table key.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.isNan&lt;br /&gt;
-- @param v&lt;br /&gt;
-- @return {boolean}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isNan(v)&lt;br /&gt;
	if type(v) == &amp;#039;number&amp;#039; and tostring(v) == &amp;#039;-nan&amp;#039; then&lt;br /&gt;
		return true&lt;br /&gt;
	else&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This returns a clone of a table. The value returned is a new table, but all&lt;br /&gt;
-- subtables and functions are shared. Metamethods are respected, but the returned&lt;br /&gt;
-- table will have no metatable of its own.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.shallowClone&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @return {table}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.shallowClone(t)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		ret[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This removes duplicate values from an array. Non-positive-integer keys are&lt;br /&gt;
-- ignored. The earliest value is kept, and all subsequent duplicate values are&lt;br /&gt;
-- removed, but otherwise the array order is unchanged.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.removeDuplicates&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @return {table}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.removeDuplicates(t)&lt;br /&gt;
	checkType(&amp;#039;removeDuplicates&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local ret, exists = {}, {}&lt;br /&gt;
	for i, v in ipairs(t) do&lt;br /&gt;
		if isNan(v) then&lt;br /&gt;
			-- NaNs can&amp;#039;t be table keys, and they are also unique, so we don&amp;#039;t need to check existence.&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		else&lt;br /&gt;
			if not exists[v] then&lt;br /&gt;
				ret[#ret + 1] = v&lt;br /&gt;
				exists[v] = true&lt;br /&gt;
			end&lt;br /&gt;
		end	&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end			&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of any numerical&lt;br /&gt;
-- keys that have non-nil values, sorted in numerical order.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.numKeys&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @return {table}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.numKeys(t)&lt;br /&gt;
	checkType(&amp;#039;numKeys&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
	local isPositiveInteger = p.isPositiveInteger&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if isPositiveInteger(k) then&lt;br /&gt;
			nums[#nums + 1] = k&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of keys with the&lt;br /&gt;
-- specified prefix and suffix. For example, for the table&lt;br /&gt;
-- {a1 = &amp;#039;foo&amp;#039;, a3 = &amp;#039;bar&amp;#039;, a6 = &amp;#039;baz&amp;#039;} and the prefix &amp;quot;a&amp;quot;, affixNums will&lt;br /&gt;
-- return {1, 3, 6}.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.affixNums&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @param[opt] {boolean} prefix&lt;br /&gt;
-- @param[opt] {boolean} suffix&lt;br /&gt;
-- @return {table}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.affixNums(t, prefix, suffix)&lt;br /&gt;
	checkType(&amp;#039;affixNums&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
	checkType(&amp;#039;affixNums&amp;#039;, 2, prefix, &amp;#039;string&amp;#039;, true)&lt;br /&gt;
	checkType(&amp;#039;affixNums&amp;#039;, 3, suffix, &amp;#039;string&amp;#039;, true)&lt;br /&gt;
&lt;br /&gt;
	local function cleanPattern(s)&lt;br /&gt;
		-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.&lt;br /&gt;
		s = s:gsub(&amp;#039;([%(%)%%%.%[%]%*%+%-%?%^%$])&amp;#039;, &amp;#039;%%%1&amp;#039;)&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	prefix = prefix or &amp;#039;&amp;#039;&lt;br /&gt;
	suffix = suffix or &amp;#039;&amp;#039;&lt;br /&gt;
	prefix = cleanPattern(prefix)&lt;br /&gt;
	suffix = cleanPattern(suffix)&lt;br /&gt;
	local pattern = &amp;#039;^&amp;#039; .. prefix .. &amp;#039;([1-9]%d*)&amp;#039; .. suffix .. &amp;#039;$&amp;#039;&lt;br /&gt;
&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if type(k) == &amp;#039;string&amp;#039; then			&lt;br /&gt;
			local num = mw.ustring.match(k, pattern)&lt;br /&gt;
			if num then&lt;br /&gt;
				nums[#nums + 1] = tonumber(num)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- Given a table with keys like (&amp;quot;foo1&amp;quot;, &amp;quot;bar1&amp;quot;, &amp;quot;foo2&amp;quot;, &amp;quot;baz2&amp;quot;), returns a table&lt;br /&gt;
-- of subtables in the format &lt;br /&gt;
-- { [1] = {foo = &amp;#039;text&amp;#039;, bar = &amp;#039;text&amp;#039;}, [2] = {foo = &amp;#039;text&amp;#039;, baz = &amp;#039;text&amp;#039;} }&lt;br /&gt;
-- Keys that don&amp;#039;t end with an integer are stored in a subtable named &amp;quot;other&amp;quot;.&lt;br /&gt;
-- The compress option compresses the table so that it can be iterated over with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.numData&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @param[opt] {boolean} compress&lt;br /&gt;
-- @return {table}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.numData(t, compress)&lt;br /&gt;
	checkType(&amp;#039;numData&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
	checkType(&amp;#039;numData&amp;#039;, 2, compress, &amp;#039;boolean&amp;#039;, true)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		local prefix, num = mw.ustring.match(tostring(k), &amp;#039;^([^0-9]*)([1-9][0-9]*)$&amp;#039;)&lt;br /&gt;
		if num then&lt;br /&gt;
			num = tonumber(num)&lt;br /&gt;
			local subtable = ret[num] or {}&lt;br /&gt;
			if prefix == &amp;#039;&amp;#039; then&lt;br /&gt;
				-- Positional parameters match the blank string; put them at the start of the subtable instead.&lt;br /&gt;
				prefix = 1&lt;br /&gt;
			end&lt;br /&gt;
			subtable[prefix] = v&lt;br /&gt;
			ret[num] = subtable&lt;br /&gt;
		else&lt;br /&gt;
			local subtable = ret.other or {}&lt;br /&gt;
			subtable[k] = v&lt;br /&gt;
			ret.other = subtable&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if compress then&lt;br /&gt;
		local other = ret.other&lt;br /&gt;
		ret = p.compressSparseArray(ret)&lt;br /&gt;
		ret.other = other&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This takes an array with one or more nil values, and removes the nil values&lt;br /&gt;
-- while preserving the order, so that the array can be safely traversed with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.compressSparseArray&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @return {table}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.compressSparseArray(t)&lt;br /&gt;
	checkType(&amp;#039;compressSparseArray&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	for _, num in ipairs(nums) do&lt;br /&gt;
		ret[#ret + 1] = t[num]&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This is an iterator for sparse arrays. It can be used like ipairs, but can&lt;br /&gt;
-- handle nil values.&lt;br /&gt;
--&lt;br /&gt;
-- @function p.sparseIpairs&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @return {function}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.sparseIpairs(t)&lt;br /&gt;
	checkType(&amp;#039;sparseIpairs&amp;#039;, 1, t, &amp;#039;table&amp;#039;)&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	local lim = #nums&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if i &amp;lt;= lim then&lt;br /&gt;
			local key = nums[i]&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- This returns the length of a table, or the first integer key n counting from&lt;br /&gt;
-- 1 such that t[n + 1] is nil. It is similar to the operator #, but may return&lt;br /&gt;
-- a different value when there are gaps in the array portion of the table.&lt;br /&gt;
-- Intended to be used on data loaded with mw.loadData. For other tables, use #.&lt;br /&gt;
-- Note: #frame.args in frame object always be set to 0, regardless of &lt;br /&gt;
-- the number of unnamed template parameters, so use this function for&lt;br /&gt;
-- frame.args.&lt;br /&gt;
-- &lt;br /&gt;
-- @function p.length&lt;br /&gt;
-- @param {table} t&lt;br /&gt;
-- @return {number}&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.length(t)&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while t[i] ~= nil do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return i - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;br /&gt;
&lt;br /&gt;
-- &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
-- (Add categories here.)&lt;/div&gt;</summary>
		<author><name>Stevium</name></author>
	</entry>
</feed>