Content deleted Content added
Improved documentation formatting. Improved isArray and added isArrayLike. Applied Johnuniq's bugfix in _deepCopy. |
implement fromIndex in inArray |
||
(21 intermediate revisions by 5 users not shown) | |||
Line 3:
-- --
-- This module includes a number of functions for dealing with Lua tables. --
-- It is a meta-module, meant to be called from other Lua modules, and should
--
------------------------------------------------------------------------------------
Line 32:
-- isNan
--
-- This function returns true if the given number is a NaN value, and false if
--
--
--
------------------------------------------------------------------------------------
function p.isNan(v)
return type(v) == 'number' and
end
Line 49:
------------------------------------------------------------------------------------
function p.shallowClone(t)
checkType('shallowClone', 1, t, 'table')
local ret = {}
for k, v in pairs(t) do
Line 63 ⟶ 64:
-- removed, but otherwise the array order is unchanged.
------------------------------------------------------------------------------------
function p.removeDuplicates(
checkType('removeDuplicates', 1,
local isNan = p.isNan
local ret, exists = {}, {}
for
if isNan(v) then
-- NaNs can't be table keys, and they are also unique, so we don't need to check existence.
ret[#ret + 1] = v
elseif not exists[v] then
end
end
return ret
end
------------------------------------------------------------------------------------
Line 91 ⟶ 90:
local isPositiveInteger = p.isPositiveInteger
local nums = {}
for k
if isPositiveInteger(k) then
nums[#nums + 1] = k
Line 97 ⟶ 96:
end
table.sort(nums)
return nums
end
Line 124 ⟶ 104:
-- This takes a table and returns an array containing the numbers of keys with the
-- specified prefix and suffix. For example, for the table
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} and the prefix "a", affixNums will return
--
------------------------------------------------------------------------------------
function p.affixNums(t, prefix, suffix)
Line 144 ⟶ 124:
local nums = {}
for k
if type(k) == 'string' then
local num = mw.ustring.match(k, pattern)
if num then
Line 159 ⟶ 139:
-- numData
--
-- Given a table with keys like
-- of subtables in the format
-- {
-- Keys that don't end with an integer are stored in a subtable named "other". The
--
-- ipairs.
------------------------------------------------------------------------------------
Line 221 ⟶ 201:
checkType('sparseIpairs', 1, t, 'table')
local nums = p.numKeys(t)
local i = 0
local lim = #nums
Line 265 ⟶ 223:
checkType('size', 1, t, 'table')
local i = 0
for
i = i + 1
end
Line 276 ⟶ 234:
if type1 ~= type2 then
return type1 < type2
return tostring(item1) < tostring(item2)
else
return item1 < item2
end
Line 283 ⟶ 243:
-- keysToList
--
-- Returns
-- comparison function or a custom keySort function.
------------------------------------------------------------------------------------
Line 289 ⟶ 249:
if not checked then
checkType('keysToList', 1, t, 'table')
checkTypeMulti('keysToList', 2, keySort, {
end
local
local index = 1
for
index = index + 1
end
if keySort ~= false then
keySort = type(keySort) == 'function' and keySort or defaultKeySort
table.sort(arr, keySort)
end
return
end
Line 317 ⟶ 276:
checkType('sortedPairs', 1, t, 'table')
checkType('sortedPairs', 2, keySort, 'function', true)
local
local i = 0
return function ()
i = i + 1
local key =
if key ~= nil then
return key, t[key]
Line 335 ⟶ 294:
-- isArray
--
-- Returns true if the given value is a table and all keys are consecutive
-- integers starting at 1.
------------------------------------------------------------------------------------
function p.isArray(v)
Line 355 ⟶ 314:
-- isArrayLike
--
-- Returns true if the given value is iterable and all keys are consecutive
-- integers starting at 1.
------------------------------------------------------------------------------------
function p.isArrayLike(v)
Line 375 ⟶ 334:
-- invert
--
-- Transposes the keys and values in an array. For example, {"a", "b", "c"} ->
--
-- the index of the last duplicate) and NaN values are ignored.
------------------------------------------------------------------------------------
function p.invert(
checkType("invert", 1,
local isNan = p.isNan
local map = {}
for i, v in ipairs(
if not isNan(v) then
map[v] = i
end
end
return map
end
Line 393 ⟶ 355:
--
-- Creates a set from the array part of the table. Indexing the set by any of the
-- values of the array returns true. For example, {"a", "b", "c"} ->
--
-- never equal to any value (including other NaNs or even themselves).
------------------------------------------------------------------------------------
function p.listToSet(
checkType("listToSet", 1,
local isNan = p.isNan
local set = {}
for _,
if not isNan(v) then
set[v] = true
end
end
return set
end
Line 413 ⟶ 378:
------------------------------------------------------------------------------------
local function _deepCopy(orig, includeMetatable, already_seen)
if type(orig) ~= "table" then
return orig
end
-- already_seen stores copies of tables indexed by the original table.
local copy = already_seen[orig]
if copy ~= nil then
Line 421 ⟶ 388:
end
copy = {}
already_seen[orig] = copy -- memoize before any recursion, to avoid infinite loops
copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen) if includeMetatable then
local mt = getmetatable(orig)
setmetatable(copy, _deepCopy(mt, true, already_seen))
end
end
return copy
end
Line 444 ⟶ 407:
function p.deepCopy(orig, noMetatable, already_seen)
checkType("deepCopy", 3, already_seen, "table", true)
return _deepCopy(orig, not noMetatable, already_seen or {})
end
Line 452 ⟶ 414:
--
-- Concatenates all values in the table that are indexed by a number, in order.
-- sparseConcat{
-- sparseConcat{
------------------------------------------------------------------------------------
function p.sparseConcat(t, sep, i, j)
local
local
for _, v in p.sparseIpairs(t) do
end
return table.concat(
end
Line 479 ⟶ 441:
------------------------------------------------------------------------------------
function p.length(t, prefix)
-- requiring module inline so that [[Module:Exponential search]] which is
--
local expSearch = require("Module:Exponential search")
checkType('length', 1, t, 'table')
checkType('length', 2, prefix, 'string', true)
return expSearch(function (i)
local key
if prefix then
Line 499 ⟶ 460:
-- inArray
--
-- Returns true if
-- Equivalent to JavaScript array.includes(searchElement) or
-- array.includes(searchElement, fromIndex), except fromIndex is 1 indexed
------------------------------------------------------------------------------------
function p.inArray(
checkType("inArray", 1,
-- if searchElement is nil, error?
fromIndex = tonumber(fromIndex)
if fromIndex then
if
fromIndex = #array + fromIndex + 1
end
if fromIndex < 1 then fromIndex = 1 end
for _, v in ipairs({unpack(array, fromIndex)}) do
if v == searchElement then
return true
end
end
else
for _, v in pairs(array) do
if v == searchElement then
return true
end
end
end
return false
end
------------------------------------------------------------------------------------
-- merge
--
-- Given the arrays, returns an array containing the elements of each input array
-- in sequence.
------------------------------------------------------------------------------------
function p.merge(...)
local arrays = {...}
local ret = {}
for i, arr in ipairs(arrays) do
checkType('merge', i, arr, 'table')
for _, v in ipairs(arr) do
ret[#ret + 1] = v
end
end
return ret
end
------------------------------------------------------------------------------------
-- extend
--
-- Extends the first array in place by appending all elements from the second
-- array.
------------------------------------------------------------------------------------
function p.extend(arr1, arr2)
checkType('extend', 1, arr1, 'table')
checkType('extend', 2, arr2, 'table')
for _, v in ipairs(arr2) do
arr1[#arr1 + 1] = v
end
end
|