Module:Table: Difference between revisions
From EverybodyWiki Bios & Wiki
WikiMaster (talk | contribs) m 1 revision imported |
m Add new revision |
||
| Line 2: | Line 2: | ||
-- A number of functions, most of them imported from [[wikt:Module:table]], a | -- A number of functions, most of them imported from [[wikt:Module:table]], a | ||
-- spinoff of [[Module:TableTools]]. | -- spinoff of [[Module:TableTools]]. | ||
local libraryUtil = require('libraryUtil') | local libraryUtil = require('libraryUtil') | ||
| Line 21: | Line 21: | ||
end | end | ||
end | end | ||
end | |||
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 | ||
end | end | ||
| Line 32: | Line 42: | ||
local check = _check('keysToList') | local check = _check('keysToList') | ||
check(1, t, 'table') | check(1, t, 'table') | ||
check(2, keySort, 'function', | check(2, keySort, { 'function', 'boolean', 'nil' }) | ||
end | end | ||
| Line 42: | Line 52: | ||
end | end | ||
if keySort ~= false then | |||
if | keySort = type(keySort) == 'function' and keySort or defaultKeySort | ||
keySort = | |||
table.sort(list, keySort) | |||
end | end | ||
return list | return list | ||
| Line 126: | Line 127: | ||
--[[ | --[[ | ||
Recursive deep copy function | Recursive deep copy function. | ||
Preserves identities of subtables. | |||
]] | ]] | ||
function | 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 | end | ||
function p.deepCopy(orig, noMetatable, already_seen) | |||
checkType("deepCopy", 3, already_seen, "table", true) | |||
return _deepCopy(orig, not noMetatable, already_seen) | |||
end | |||
--[[ | --[[ | ||
| Line 163: | Line 184: | ||
end | end | ||
--[[ | |||
-- This returns the length of a table, or the first integer key n counting from | |||
-- 1 such that t[n + 1] is nil. 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 #. | |||
--]] | |||
function p.length(t) | |||
local i = 0 | |||
repeat | |||
i = i + 1 | |||
until t[i] == nil | |||
return i - 1 | |||
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 | |||
return p | return p | ||
Latest revision as of 14:59, 14 March 2019
local p = {}
-- A number of functions, most of them imported from [[wikt:Module:table]], a
-- spinoff of [[Module:TableTools]].
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local function _check(funcName, expectType)
if type(expectType) == "string" then
return function(argIndex, arg, nilOk)
checkType(funcName, argIndex, arg, expectType, nilOk)
end
else
return function(argIndex, arg, expectType, nilOk)
if type(expectType) == "table" then
checkTypeMulti(funcName, argIndex, arg, expectType, nilOk)
else
checkType(funcName, argIndex, arg, expectType, nilOk)
end
end
end
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
local check = _check('keysToList')
check(1, t, 'table')
check(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)
local check = _check('keysToList')
check(1, t, 'table')
check(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 require("Module:TableTools").sparseIpairs(t) do
list_i = list_i + 1
list[list_i] = v
end
return table.concat(list, sep, i, j)
end
--[[
-- This returns the length of a table, or the first integer key n counting from
-- 1 such that t[n + 1] is nil. 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 #.
--]]
function p.length(t)
local i = 0
repeat
i = i + 1
until t[i] == nil
return i - 1
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
return p
