Changes

Jump to navigation Jump to search
m
Changed protection level for "Module:TableTools": High-risk Lua module: bumping protection level due to high usage, plus the stability of the module. See https://en.wikipedia.org/w/index.php?title=Wikipedia:Requests_for_page_protection&oldid=983044034#Module:TableTools ([Edit=Require administrator access] (indefinite) [Move=Require administrator access] (indefinite))
Line 17: Line 17:  
local infinity = math.huge
 
local infinity = math.huge
 
local checkType = libraryUtil.checkType
 
local checkType = libraryUtil.checkType
 +
local checkTypeMulti = libraryUtil.checkTypeMulti
    
--[[
 
--[[
Line 29: Line 30:  
--]]
 
--]]
 
function p.isPositiveInteger(v)
 
function p.isPositiveInteger(v)
if type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity then
+
return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity
return true
  −
else
  −
return false
  −
end
   
end
 
end
   Line 47: Line 44:  
--]]
 
--]]
 
function p.isNan(v)
 
function p.isNan(v)
if type(v) == 'number' and tostring(v) == '-nan' then
+
return type(v) == 'number' and tostring(v) == '-nan'
return true
  −
else
  −
return false
  −
end
   
end
 
end
   Line 136: Line 129:  
local function cleanPattern(s)
 
local function cleanPattern(s)
 
-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.
 
-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.
s = s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
+
return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
return s
   
end
 
end
   Line 251: Line 243:  
------------------------------------------------------------------------------------
 
------------------------------------------------------------------------------------
 
--]]
 
--]]
 +
 
function p.size(t)
 
function p.size(t)
 
checkType('size', 1, t, 'table')
 
checkType('size', 1, t, 'table')
Line 258: Line 251:  
end
 
end
 
return i
 
return i
 +
end
 +
 +
 +
local function defaultKeySort(item1, item2)
 +
-- "number" < "string", so numbers will be sorted before strings.
 +
local type1, type2 = type(item1), type(item2)
 +
if type1 ~= type2 then
 +
return type1 < type2
 +
else -- This will fail with table, boolean, function.
 +
return item1 < item2
 +
end
 +
end
 +
 +
--[[
 +
Returns a list of the keys in a table, sorted using either a default
 +
comparison function or a custom keySort function.
 +
]]
 +
function p.keysToList(t, keySort, checked)
 +
if not checked then
 +
checkType('keysToList', 1, t, 'table')
 +
checkTypeMulti('keysToList', 2, keySort, { 'function', 'boolean', 'nil' })
 +
end
 +
 +
local list = {}
 +
local index = 1
 +
for key, value in pairs(t) do
 +
list[index] = key
 +
index = index + 1
 +
end
 +
 +
if keySort ~= false then
 +
keySort = type(keySort) == 'function' and keySort or defaultKeySort
 +
 +
table.sort(list, keySort)
 +
end
 +
 +
return list
 +
end
 +
 +
--[[
 +
Iterates through a table, with the keys sorted using the keysToList function.
 +
If there are only numerical keys, sparseIpairs is probably more efficient.
 +
]]
 +
function p.sortedPairs(t, keySort)
 +
checkType('sortedPairs', 1, t, 'table')
 +
checkType('sortedPairs', 2, keySort, 'function', true)
 +
 +
local list = p.keysToList(t, keySort, true)
 +
 +
local i = 0
 +
return function()
 +
i = i + 1
 +
local key = list[i]
 +
if key ~= nil then
 +
return key, t[key]
 +
else
 +
return nil, nil
 +
end
 +
end
 +
end
 +
 +
--[[
 +
Returns true if all keys in the table are consecutive integers starting at 1.
 +
--]]
 +
function p.isArray(t)
 +
checkType("isArray", 1, t, "table")
 +
 +
local i = 0
 +
for k, v in pairs(t) do
 +
i = i + 1
 +
if t[i] == nil then
 +
return false
 +
end
 +
end
 +
return true
 +
end
 +
 +
-- { "a", "b", "c" } -> { a = 1, b = 2, c = 3 }
 +
function p.invert(array)
 +
checkType("invert", 1, array, "table")
 +
 +
local map = {}
 +
for i, v in ipairs(array) do
 +
map[v] = i
 +
end
 +
 +
return map
 +
end
 +
 +
--[[
 +
{ "a", "b", "c" } -> { ["a"] = true, ["b"] = true, ["c"] = true }
 +
--]]
 +
function p.listToSet(t)
 +
checkType("listToSet", 1, t, "table")
 +
 +
local set = {}
 +
for _, item in ipairs(t) do
 +
set[item] = true
 +
end
 +
 +
return set
 +
end
 +
 +
--[[
 +
Recursive deep copy function.
 +
Preserves identities of subtables.
 +
 +
]]
 +
local function _deepCopy(orig, includeMetatable, already_seen)
 +
-- Stores copies of tables indexed by the original table.
 +
already_seen = already_seen or {}
 +
 +
local copy = already_seen[orig]
 +
if copy ~= nil then
 +
return copy
 +
end
 +
 +
if type(orig) == 'table' then
 +
copy = {}
 +
for orig_key, orig_value in pairs(orig) do
 +
copy[deepcopy(orig_key, includeMetatable, already_seen)] = deepcopy(orig_value, includeMetatable, already_seen)
 +
end
 +
already_seen[orig] = copy
 +
 +
if includeMetatable then
 +
local mt = getmetatable(orig)
 +
if mt ~= nil then
 +
local mt_copy = deepcopy(mt, includeMetatable, already_seen)
 +
setmetatable(copy, mt_copy)
 +
already_seen[mt] = mt_copy
 +
end
 +
end
 +
else -- number, string, boolean, etc
 +
copy = orig
 +
end
 +
return copy
 +
end
 +
 +
function p.deepCopy(orig, noMetatable, already_seen)
 +
checkType("deepCopy", 3, already_seen, "table", true)
 +
 +
return _deepCopy(orig, not noMetatable, already_seen)
 +
end
 +
 +
--[[
 +
Concatenates all values in the table that are indexed by a number, in order.
 +
sparseConcat{ a, nil, c, d }  =>  "acd"
 +
sparseConcat{ nil, b, c, d }  =>  "bcd"
 +
]]
 +
function p.sparseConcat(t, sep, i, j)
 +
local list = {}
 +
 +
local list_i = 0
 +
for _, v in p.sparseIpairs(t) do
 +
list_i = list_i + 1
 +
list[list_i] = v
 +
end
 +
 +
return table.concat(list, sep, i, j)
 +
end
 +
 +
--[[
 +
-- Finds the length of an array, or of a quasi-array with keys such
 +
-- as "data1", "data2", etc., using an exponential search algorithm.
 +
-- It is similar to the operator #, but may return
 +
-- a different value when there are gaps in the array portion of the table.
 +
-- Intended to be used on data loaded with mw.loadData. For other tables, use #.
 +
-- Note: #frame.args in frame object always be set to 0, regardless of
 +
-- the number of unnamed template parameters, so use this function for
 +
-- frame.args.
 +
--]]
 +
 +
function p.length(t, prefix)
 +
-- requiring module inline so that [[Module:Exponential search]]
 +
-- which is only needed by this one function
 +
-- doesn't get millions of transclusions
 +
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
 +
key = prefix .. tostring(i)
 +
else
 +
key = i
 +
end
 +
return t[key] ~= nil
 +
end) or 0
 +
end
 +
function p.inArray(arr, valueToFind)
 +
checkType("inArray", 1, arr, "table")
 +
 +
-- if valueToFind is nil, error?
 +
 +
for _, v in ipairs(arr) do
 +
if v == valueToFind then
 +
return true
 +
end
 +
end
 +
 +
return false
 
end
 
end
    
return p
 
return p

Navigation menu