Módulo:TableTools/Testes
Esta é a página de testes de módulos de Módulo:TableTools (dif). |
Este módulo depende dos seguintes outros módulos: |
Este módulo inclui várias funções para lidar com tabelas Lua. É um metamódulo, destinado a ser chamado a partir de outros módulos Lua e não deve ser chamado diretamente a partir de "#invoke".
Carregando o módulo
editarPara usar qualquer uma das funções, primeiro é necessário carregar o módulo.
local TableTools = require('Módulo:TableTools/Testes')
isPositiveInteger
editarTableTools.isPositiveInteger(value)
Esta função retorna true
se value
for um número inteiro positivo e false
se não for. Embora não opere em tabelas, está incluída aqui porque é útil para determinar se uma determinada chave de tabela está na parte arranjo ou na parte hash de uma tabela.
isNan
editarTableTools.isNan(value)
Esta função retorna true
se value
for um valor NaN e false
se não for. Embora não opere em tabelas, está incluída aqui porque é útil para determinar se um valor pode ser uma chave de tabela válida. (Lua gerará um erro se um valor NaN for usado como uma chave de tabela.)
shallowClone
editarTableTools.shallowClone(t)
Esta função retorna um clone de uma tabela. O valor retornado é uma nova tabela, mas todas as subtabelas e funções são compartilhadas. Os metamétodos são respeitados, mas a tabela retornada não terá metatabela própria. Se você quiser criar uma nova tabela sem subtabelas compartilhadas e com metatabelas transferidas, você pode usar mw.clone
. Se você deseja criar uma nova tabela sem subtabelas compartilhadas e sem metatabelas transferidas, use deepCopy
com a opção noMetatable
.
removeDuplicates
editarTableTools.removeDuplicates(t)
Esta função remove valores duplicados de um arranjo. Esta função foi projetada para funcionar apenas com arranjos padrões: as chaves que não são números inteiros positivos são ignoradas, assim como todos os valores após o primeiro valor nil
. (Para arranjos contendo valores nil
, você pode usar compressSparseArray
primeiro.) A função tenta preservar a ordem do arranjo: o primeiro valor que não for exclusivo (único) é mantido e todos os valores duplicados subsequentes são removidos. Por exemplo, para a tabela {5, 4, 4, 3, 4, 2, 2, 1}
removeDuplicates
retornará {5, 4, 3, 2, 1}
.
numKeys
editarTableTools.numKeys(t)
Esta função pega uma tabela t
e retorna um arranjo contendo os números de quaisquer chaves inteiras positivas que tenham valores que não são nulos, classificados em ordem numérica. Por exemplo, para a tabela {'foo', nil, 'bar', 'baz', a = 'b'}
, numKeys
retornará {1, 3, 4}
.
affixNums
editarTableTools.affixNums(t, prefix, suffix)
Esta função pega uma tabela t
e retorna um arranjo contendo os números de chaves com o prefixo opcional prefix
e o sufixo opcional suffix
. Por exemplo, para a tabela {a1 = 'foo', a3 = 'bar', a6 = 'baz'}
e o prefixo 'a'
, affixNums
retornará {1, 3, 6}
. Todos os caracteres em prefix
e suffix
são interpretados literalmente.
numData
editarTableTools.numData(t, compress)
Dada uma tabela com chaves como "foo1"
, "bar1"
, "foo2"
e "baz2"
, esta função retorna uma tabela de subtabelas no formato { [1] = {foo = 'text', bar = 'text'}, [2] = {foo = 'text', baz = 'text' } }
. As chaves que não terminam com um número inteiro são armazenadas em uma subtabela chamada "other"
. A opção "compress" comprime a tabela para que possa ser iterada com ipairs
.
compressSparseArray
editarTableTools.compressSparseArray(t)
Esta função pega um arranjo t
com um ou mais valores nulos, e remove os valores nulos enquanto preserva a ordem, para que o arranjo possa ser percorrido com segurança com ipairs
. Quaisquer chaves que não sejam números inteiros positivos são removidas. Por exemplo, para a tabela {1, nil, foo = 'bar', 3, 2}
, compressSparseArray
retornará {1, 3, 2}
.
sparseIpairs
editarTableTools.sparseIpairs(t)
Esta é uma função iteradora para percorrer um arranjo esparso t
. É semelhante a ipairs
, mas continuará a iterar até a chave numérica mais alta, enquanto ipairs
pode parar após o primeiro valor nil
. Quaisquer chaves que não sejam números inteiros positivos são ignoradas.
Normalmente, sparseIpairs
é usada em um loop for
genérico.
for i, v in TableTools.sparseIpairs(t) do
-- bloco de código
end
Observe que sparseIpairs
usa a função pairs
em sua implementação. Embora algumas chaves da tabela pareçam ser ignoradas, todas as chaves da tabela são acessadas quando ela é executado.
size
editarTableTools.size(t)
Localiza o tamanho de uma tabela de pares chave/valor. Por exemplo, para a tabela {foo = 'foo', bar = 'bar'}
, size
retornará 2
. A função também funcionará em arranjos, mas para arranjos é mais eficiente usar o operador #
. Observe que para encontrar o tamanho da tabela, esta função usa a função pairs
para percorrer todas as chaves da tabela.
keysToList
editarTableTools.keysToList(t, keySort, checked)
Esta função retorna uma lista das chaves em uma tabela, classificadas usando uma função de comparação padrão ou uma função keySort
personalizada, que segue as mesmas regras da função comp
fornecida para table.sort
. Se keySort
for false
, nenhuma classificação será feita. É necessário definir checked
como true
para pular a verificação interna de tipo.
sortedPairs
editarTableTools.sortedPairs(t, keySort)
Esta função itera por meio de uma tabela, com as chaves classificadas usando a função keysToList
. Se houver apenas chaves numéricas, sparseIpairs
provavelmente será mais eficiente.
isArray
editarTableTools.isArray(value)
Esta função retorna true
se value
for uma tabela e todas as chaves forem inteiros consecutivos começando em 1.
isArrayLike
editarTableTools.isArrayLike(value)
Esta função retorna true
se value
for iterável e todas as chaves forem inteiros consecutivos começando em 1.
invert
editarTableTools.invert(arr)
Esta função transpõe as chaves e valores em um arranjo. Por exemplo, invert{ "a", "b", "c" }
resulta em { a=1, b=2, c=3 }
.
listToSet
editarTableTools.listToSet(arr)
Esta função cria um conjunto a partir da parte arranjo da tabela arr
. A indexação do conjunto por qualquer um dos valores do arranjo retorna true
. Por exemplo, listToSet{ "a", "b", "c" }
resulta em { a=true, b=true, c=true }
. Consulte também Módulo:Lua set [en] para formas mais avançadas de criar um conjunto.
deepCopy
editarTableTools.deepCopy(orig, noMetatable, alreadySeen)
Esta função cria uma cópia da tabela orig
. Como em mw.clone
, todos os valores que não são funções são duplicados e a identidade das tabelas é preservada. Se noMetatable
for true
, então a metatabela (se houver) não será copiada. Ela pode copiar tabelas carregadas com mw.loadData
.
Similar à mw.clone
, mas mw.clone
não pode copiar tabelas carregadas com mw.loadData
e não permite que metatabelas não sejam copiadas.
sparseConcat
editarTableTools.sparseConcat(t, sep, i, j)
Esta função concatena todos os valores na tabela que são indexados por um número inteiro positivo, em ordem. Por exemplo, sparseConcat{ "a", nil, "c", "d" }
resulta em "acd"
e sparseConcat{ nil, "b ", "c", "d" }
resulta em "bcd"
.
length
editarTableTools.length(t, prefix)
Esta função localiza o comprimento de um arranjo ou de um quasi-arranjo com chaves com um prefix
opcional como "data1", "data2", etc. Ela usa um algoritmo de pesquisa exponencial para encontrar o comprimento, de modo a usar o mínimo possível de pesquisas de tabela.
Este algoritmo é útil para arranjos que usam metatabelas (por exemplo, frame.args) e para quasi-arranjos. Para arranjos normais, basta usar o operador #, pois ele é implementado em C e será mais rápido.
inArray
editarTableTools.inArray(arr, valueToFind)
Esta função retorna true
se valueToFind
for um membro do arranjo arr
e false
se não for.
------------------------------------------------------------------------------------
-- TableTools --
-- --
-- Este módulo inclui várias funções para lidar com tabelas Lua. --
-- É um metamódulo, destinado a ser chamado a partir de outros módulos Lua, e --
-- não deve ser chamado diretamente a partir de "#invoke". --
------------------------------------------------------------------------------------
local libraryUtil = require('libraryUtil')
local p = {}
-- Define variáveis e funções usadas com frequência.
local floor = math.floor
local infinity = math.huge
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
------------------------------------------------------------------------------------
-- isPositiveInteger
--
-- Esta função retorna "true" se o valor fornecido for um número inteiro positivo e
-- "false" se não. Embora não opere em tabelas, ela é incluída aqui porque ela é
-- útil para determinar se uma determinada chave de tabela está na parte de arranjo
-- ou na parte de 'hash' de uma tabela.
------------------------------------------------------------------------------------
function p.isPositiveInteger(v)
return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity
end
------------------------------------------------------------------------------------
-- isNan
--
-- Essa função retorna "true" se o número fornecido for um valor de "NaN" e "false"
-- se não. Embora não opere em tabelas, ela é incluída aqui porque ela é útil para
-- determinar se um valor pode ser uma chave de tabela válida. Lua irá gerar um
-- erro se um "NaN" for usado como uma chave de tabela.
------------------------------------------------------------------------------------
function p.isNan(v)
return type(v) == 'number' and v ~= v
end
------------------------------------------------------------------------------------
-- shallowClone
--
-- Essa função retorna um clone de uma tabela. O valor retornado é uma nova tabela,
-- mas todas as subtabelas e funções são compartilhadas. Os metamétodos são
-- respeitados, mas a tabela retornada não terá metatabela própria.
------------------------------------------------------------------------------------
function p.shallowClone(t)
checkType('shallowClone', 1, t, 'table')
local ret = {}
for k, v in pairs(t) do
ret[k] = v
end
return ret
end
------------------------------------------------------------------------------------
-- removeDuplicates
--
-- Essa função remove os valores duplicados de um arranjo. As chaves de
-- números inteiros que não são positivos são ignoradas. O valor mais antigo é
-- mantido e todos os valores duplicados subsequentes são removidos, mas caso não,
-- a ordem do arranjo permanece inalterada.
------------------------------------------------------------------------------------
function p.removeDuplicates(arr)
checkType('removeDuplicates', 1, arr, 'table')
local isNan = p.isNan
local ret, exists = {}, {}
for _, v in ipairs(arr) do
if isNan(v) then
-- Os "NaN"s não podem ser chaves de tabela e também são únicos,
-- portanto não precisamos verificar a existência.
ret[#ret + 1] = v
else
if not exists[v] then
ret[#ret + 1] = v
exists[v] = true
end
end
end
return ret
end
------------------------------------------------------------------------------------
-- numKeys
--
-- Essa função pega uma tabela e retorna um arranjo contendo os números
-- de quaisquer chaves numéricas que tenham valores que não são nulos,
-- classificados em ordem numérica.
------------------------------------------------------------------------------------
function p.numKeys(t)
checkType('numKeys', 1, t, 'table')
local isPositiveInteger = p.isPositiveInteger
local nums = {}
for k in pairs(t) do
if isPositiveInteger(k) then
nums[#nums + 1] = k
end
end
table.sort(nums)
return nums
end
------------------------------------------------------------------------------------
-- affixNums
--
-- Essa função pega uma tabela e retorna um arranjo contendo os números
-- de chaves com o prefixo e sufixo especificados. Por exemplo, para a tabela
-- {a1 = 'foo', a3 = 'bar', a6 = 'baz'} e o prefixo "a", "affixNums" retornará
-- {1, 3, 6}.
------------------------------------------------------------------------------------
function p.affixNums(t, prefix, suffix)
checkType('affixNums', 1, t, 'table')
checkType('affixNums', 2, prefix, 'string', true)
checkType('affixNums', 3, suffix, 'string', true)
local function cleanPattern(s)
-- Limpa um padrão ('pattern') para que os caracteres mágicos "()%.[]*+-?^$"
-- sejam interpretados literalmente.
return s:gsub('([%(%)%%%.%[%]%*%+%-%?%^%$])', '%%%1')
end
prefix = prefix or ''
suffix = suffix or ''
prefix = cleanPattern(prefix)
suffix = cleanPattern(suffix)
local pattern = '^' .. prefix .. '([1-9]%d*)' .. suffix .. '$'
local nums = {}
for k in pairs(t) do
if type(k) == 'string' then
local num = mw.ustring.match(k, pattern)
if num then
nums[#nums + 1] = tonumber(num)
end
end
end
table.sort(nums)
return nums
end
------------------------------------------------------------------------------------
-- numData
--
-- Dada uma tabela com chaves como {"foo1", "bar1", "foo2", "baz2"}, essa função
-- retorna uma tabela de subtabelas no formato
-- {[1] = {foo = 'texto', bar = 'texto'}, [2] = {foo = 'texto', baz = 'texto'}}.
-- As chaves que não terminam com um número inteiro são armazenadas em uma
-- subtabela chamada "other". A opção "compress" comprime a tabela para que ela
-- possa ser iterada com "ipairs".
------------------------------------------------------------------------------------
function p.numData(t, compress)
checkType('numData', 1, t, 'table')
checkType('numData', 2, compress, 'boolean', true)
local ret = {}
for k, v in pairs(t) do
local prefix, num = mw.ustring.match(tostring(k), '^([^0-9]*)([1-9][0-9]*)$')
if num then
num = tonumber(num)
local subtable = ret[num] or {}
if prefix == '' then
-- Os parâmetros posicionais correspondem à sequência em branco;
-- coloca-os no início da subtabela.
prefix = 1
end
subtable[prefix] = v
ret[num] = subtable
else
local subtable = ret.other or {}
subtable[k] = v
ret.other = subtable
end
end
if compress then
local other = ret.other
ret = p.compressSparseArray(ret)
ret.other = other
end
return ret
end
------------------------------------------------------------------------------------
-- compressSparseArray
--
-- Essa função pega um arranjo com um ou mais valores nulos e
-- remove os valores nulos enquanto preserva a ordem, para que o arranjo
-- possa ser percorrido com segurança com "ipairs".
------------------------------------------------------------------------------------
function p.compressSparseArray(t)
checkType('compressSparseArray', 1, t, 'table')
local ret = {}
local nums = p.numKeys(t)
for _, num in ipairs(nums) do
ret[#ret + 1] = t[num]
end
return ret
end
------------------------------------------------------------------------------------
-- sparseIpairs
--
-- Esta função é uma iteradora para arranjos esparsos. Ela pode ser
-- usada como "ipairs", mas pode manipular valores nulos.
------------------------------------------------------------------------------------
function p.sparseIpairs(t)
checkType('sparseIpairs', 1, t, 'table')
local nums = p.numKeys(t)
local i = 0
local lim = #nums
return function ()
i = i + 1
if i <= lim then
local key = nums[i]
return key, t[key]
else
return nil, nil
end
end
end
------------------------------------------------------------------------------------
-- size
--
-- Essa função retorna o tamanho de uma tabela de pares chave/valor. Ela também
-- funcionará em arranjos, mas para arranjos é mais eficiente usar o operador #.
------------------------------------------------------------------------------------
function p.size(t)
checkType('size', 1, t, 'table')
local i = 0
for _ in pairs(t) do
i = i + 1
end
return i
end
local function defaultKeySort(item1, item2)
-- número < sequência, então os números serão ordenados antes das sequências.
local type1, type2 = type(item1), type(item2)
if type1 ~= type2 then
return type1 < type2
elseif type1 == 'table' or type1 == 'boolean' or type1 == 'function' then
return tostring(item1) < tostring(item2)
else
return item1 < item2
end
end
------------------------------------------------------------------------------------
-- keysToList
--
-- Essa função retorna um arranjo das chaves em uma tabela, ordenada
-- usando uma função de comparação padrão ou uma função "keySort" personalizada.
------------------------------------------------------------------------------------
function p.keysToList(t, keySort, checked)
if not checked then
checkType('keysToList', 1, t, 'table')
checkTypeMulti('keysToList', 2, keySort, {'function', 'boolean', 'nil'})
end
local arr = {}
local index = 1
for k in pairs(t) do
arr[index] = k
index = index + 1
end
if keySort ~= false then
keySort = type(keySort) == 'function' and keySort or defaultKeySort
table.sort(arr, keySort)
end
return arr
end
------------------------------------------------------------------------------------
-- sortedPairs
--
-- Essa função itera por meio de uma tabela, com as chaves ordenadas usando a
-- função "keysToList". Se houver apenas chaves numéricas, "sparseIpairs"
-- provavelmente será mais eficiente.
------------------------------------------------------------------------------------
function p.sortedPairs(t, keySort)
checkType('sortedPairs', 1, t, 'table')
checkType('sortedPairs', 2, keySort, 'function', true)
local arr = p.keysToList(t, keySort, true)
local i = 0
return function ()
i = i + 1
local key = arr[i]
if key ~= nil then
return key, t[key]
else
return nil, nil
end
end
end
------------------------------------------------------------------------------------
-- isArray
--
-- Essa função retorna "true" se o valor fornecido for uma tabela e todas as chaves
-- forem números inteiros consecutivos começando em 1.
------------------------------------------------------------------------------------
function p.isArray(v)
if type(v) ~= 'table' then
return false
end
local i = 0
for _ in pairs(v) do
i = i + 1
if v[i] == nil then
return false
end
end
return true
end
------------------------------------------------------------------------------------
-- isArrayLike
--
-- Essa função retorna "true" se o valor fornecido for iterável e todas as chaves
-- forem números inteiros consecutivos começando em 1.
------------------------------------------------------------------------------------
function p.isArrayLike(v)
if not pcall(pairs, v) then
return false
end
local i = 0
for _ in pairs(v) do
i = i + 1
if v[i] == nil then
return false
end
end
return true
end
------------------------------------------------------------------------------------
-- invert
--
-- Essa função transpõe as chaves e valores em um arranjo. Por exemplo,
-- {"a", "b", "c"} -> {a = 1, b = 2, c = 3}. As duplicatas não são suportadas (os
-- valores dos resultados referem-se ao índice da última duplicata) e os valores
-- "NaN" são ignorados.
------------------------------------------------------------------------------------
function p.invert(arr)
checkType("invert", 1, arr, "table")
local isNan = p.isNan
local map = {}
for i, v in ipairs(arr) do
if not isNan(v) then
map[v] = i
end
end
return map
end
------------------------------------------------------------------------------------
-- listToSet
--
-- Essa função cria um conjunto a partir da parte do arranjo da tabela.
-- A indexação do conjunto por qualquer um dos valores do arranjo retorna
-- "true". Por exemplo, {"a", "b", "c"} -> {a = true, b = true, c = true}. Os
-- valores "NaN" são ignorados, pois Lua os considera como nunca sendo iguais a
-- qualquer valor (incluindo outros "NaN"s ou até eles mesmos).
------------------------------------------------------------------------------------
function p.listToSet(arr)
checkType("listToSet", 1, arr, "table")
local isNan = p.isNan
local set = {}
for _, v in ipairs(arr) do
if not isNan(v) then
set[v] = true
end
end
return set
end
------------------------------------------------------------------------------------
-- deepCopy
--
-- Função de cópia profunda recursiva. Preserva as identidades das subtabelas.
------------------------------------------------------------------------------------
local function _deepCopy(orig, includeMetatable, already_seen)
-- Armazena as cópias das tabelas indexadas pela tabela original.
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
------------------------------------------------------------------------------------
-- sparseConcat
--
-- Essa função concatena todos os valores na tabela que são indexados por um número,
-- em ordem.
-- "sparseConcat{a, nil, c, d}" => "acd"
-- "sparseConcat{nil, b, c, d}" => "bcd"
------------------------------------------------------------------------------------
function p.sparseConcat(t, sep, i, j)
local arr = {}
local arr_i = 0
for _, v in p.sparseIpairs(t) do
arr_i = arr_i + 1
arr[arr_i] = v
end
return table.concat(arr, sep, i, j)
end
------------------------------------------------------------------------------------
-- length
--
-- Essa função localiza o comprimento de um arranjo ou de um
-- quase-arranjo com chaves como "data1", "data2" etc., usando um
-- algoritmo de pesquisa exponencial. Ela é semelhante ao operador #, mas pode
-- retornar um valor diferente quando houver lacunas na parte do arranjo
-- da tabela. Destina-se a ser usada em dados carregados com "mw.loadData". Para
-- outras tabelas, use #.
-- Observação: "#frame.args" no objeto "frame" sempre será definido como 0,
-- independentemente do número de parâmetros de predefinição sem nome, portanto,
-- use esta função para "frame.args".
------------------------------------------------------------------------------------
function p.length(t, prefix)
-- Exige módulo embutido, de modo que
-- [[Módulo:Exponential search]] que é necessário
-- somente para esta função, não obtenha milhões de transclusões.
local expSearch = require("Módulo: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
------------------------------------------------------------------------------------
-- inArray
--
-- Essa função Retorna "true" se "valueToFind" for um membro do arranjo
-- e "false" se não.
------------------------------------------------------------------------------------
function p.inArray(arr, valueToFind)
checkType("inArray", 1, arr, "table")
-- se "valueToFind" for nulo, erro?
for _, v in ipairs(arr) do
if v == valueToFind then
return true
end
end
return false
end
return p