Differenze tra le versioni di "Modulo:Wikilib/tables"

Adding flatMap
(Bugfix *** sovrascritto il testo esistente ***)
(Adding flatMap)
-- luacheck: new_globals table
-- Funzioni di libreria per le tabelle
-- Library table functions
 
local t = {}
 
-- Stateless iterator sulle chiavion non-integer interekeys
local nextNonInt = function(tab, key)
local nextKey, nextValue = key
repeat
nextKey, nextValue = next(tab, nextKey)
until type(nextKey) ~= 'number'
or math.floor(nextKey) ~= nextKey
return nextKey, nextValue
end
 
local next_non_int = nextNonInt -- luacheck: no unused
 
-- Stateless iterator dato usarebe neiused genericin for loops
table.nonIntPairs = function(tab)
return nextNonInt, tab
end
 
table.non_int_pairs = t.nonIntPairs
t.nonIntPairs, t.non_int_pairs =
table.nonIntPairs, table.nonIntPairs
 
-- Returns true only if a is lexigographically greater than b
--[[
 
Ritorna true se a è lessicograficamente
maggiore di b, false altrimenti
 
--]]
local minor = function(a, b)
if not b then
return true
end
 
--[[
Necessario affinché roba come 1 e
'01' siano considerati uguali
--]]
local nA, nB = tonumber(a), tonumber(b)
if nA and nB then
return nA < nB
end
 
return tostring(a) < tostring(b)
end
 
table.search = function(tab, value)
for k, v in pairs(tab) do
if v == value then
return k
end
end
-- No explicit return, thus nil
 
table.linearSearch, table.linear_search =
table.search, table.search
t.search, t.linearSearch, t.linear_search =
table.search, table.search, table.search
 
--[[
--]]
table.deepSearch = function(tab, value)
for k, v in pairs(tab) do
if v == value then
return k
end
if type(v) == 'table' then
--[[
If the last list element is not nil, value
has been found, thus returning
--]]
local valueKeys = {table.deepSearch(v, value)}
if valueKeys[#valueKeys] then
return k, unpack(valueKeys)
end
end
end
end
-- No explicit return, thus nil
end
 
table.deep_search, table.recursiveSearch, table.recursive_search =
table.deepSearch, table.deepSearch, table.deepSearch
t.deepSearch, t.deep_search, t.recursiveSearch, t.recursive_search =
table.deepSearch, table.deepSearch, table.deepSearch, table.deepSearch
 
--[[
--]]
table.getn = function(self, count)
count = count or 'all'
local n = 0
local iterator
local iterator = nil
if count == true or tostring(count):lower() == 'num' then
iterator = ipairs
else
iterator = pairs
end
for k_ in iterator(self) do
n = n + 1
end
return n
end
 
--]]
table.tableKeysAlias = function(tab, source, dest)
for destGroup, sourceKey in ipairs(source) do
for k_, destKey in ipairs(dest[destGroup]) do
tab[destKey] = tab[sourceKey]
end
end
end
 
table.table_keys_alias, table.keysAlias, table.keys_alias =
table.tableKeysAlias, table.tableKeysAlias, table.tableKeysAlias
t.tableKeysAlias, t.table_keys_alias, t.keysAlias, t.keys_alias =
table.tableKeysAlias, table.tableKeysAlias, table.tableKeysAlias, table.tableKeysAlias
 
--[[
--]]
table.map = function(tab, funct, iter)
iter = iter or pairs
 
local dest = {}
for key, value in iter(tab) do
dest[key] = funct(value, key)
end
return dest
end
 
t.map = table.map
 
--[[
 
Applies a function over all of the elements of a table returned by the passed
iterator. The function is expected to return a list. The lists produced from
the elements are merged together in the same way as table.merge would do. The
iterator defaults to pairs.
 
The function takes as input an element and its ke, in this order: in fact, the
key is often unnecessary, and would just clutter the code in these cases.
 
--]]
table.flatMap = function(tab, funct, iter)
iter = iter or pairs
 
local dest = {}
for k, v in iter(tab) do
dest = table.merge(dest, funct(v, k))
end
return dest
end
 
table.flat_map = table.flatMap
t.flatMap, t.fat_map = table.flatMap, table.flatMap
 
--[[
--]]
table.mapToNum = function(tab, funct, iter)
iter = iter or pairs
 
local dest = {}
for key, value in iter(tab) do
table.insert(dest, funct(value, key))
end
return dest
end
 
table.map_to_num, table.mapToNumeric, table.map_to_numeric
= table.mapToNum, table.mapToNum, table.mapToNum
t.mapToNum, t.map_to_num, t.mapToNumeric, t.map_to_numeric
= table.mapToNum, table.mapToNum, table.mapToNum,
table.mapToNum
 
--[[
 
Applies a function over all of the elements of a table returned by the passed
iterator. The function is expected to return a list. The lists produced from
the elements are converted to numeric lists: the order of the elements is
determined by the given iterator. These lists are then concatenated together,
in the order the elements of the initial list are returned by the iterator.
 
The function takes as input an element and its ke, in this order: in fact, the
key is often unnecessary, and would just clutter the code in these cases.
 
--]]
table.flatMapToNum = function(tab, funct, iter)
iter = iter or pairs
 
local dest = {}
for k, v in iter(tab) do
for _, value in iter(funct(v, k)) do
table.insert(dest, value)
end
end
return dest
end
 
table.flat_map_to_num, table.flatMapToNumeric, table.flat_map_to_numeric
= table.flatMapToNum, table.flatMapToNum, table.flatMapToNum
t.flatMapToNum, t.flat_map_to_num, t.flatMapToNumeric, t.flat_map_to_numeric
= table.flatMapToNum, table.flatMapToNum, table.flatMapToNum,
table.flatMapToNum
 
--[[
 
Returns true if at least one of the elements in the list satisties a predicate.
elements in the list satisties a
predicate.
 
The predicate function takes the value as the first argument, then the key;
usual key-value order is reversed because the key is often unnecessary, and
first argument, then the key; usual key-value
having it last leads to nicer syntax in the call site.
order is reversed because the key is often
unnecessary, and having it last leads to nicer
syntax in callers.
 
--]]
--[[
 
Returns true if all of the elements in the list satisties a predicate.
in the list satisties a predicate.
 
The predicate function takes the value as the first argument, then the key;
usual key-value order is reversed because the key is often unnecessary, and
first argument, then the key; usual key-value
having it last leads to nicer syntax in the call site.
order is reversed because the key is often
unnecessary, and having it last leads to nicer
syntax in callers.
 
--]]
return table.fold(tab, true,
function(acc, value, key)
return funct(valyevalue, key) and acc
end, iter)
end
table.equal = function(tab1, tab2)
 
--[[
Si confrontano direttamente gli argomenti se
uno dei due ha il metamethod __eq o se uno
dei due non è una table
--]]
local mt1 = getmetatable(tab1)
local mt2 = getmetatable(tab2)
if mt1 and mt1.__eq or mt2 and mt2.__eq
or type(tab1) ~= 'table'
or type(tab2) ~= 'table' then
return tab1 == tab2
end
 
--[[
Se si hanno due riferimenti alla stessa
table si evitano molte computazioni inutili
--]]
if tab1 == tab2 then
return true
end
 
--[[
Se il numero di elementi è diverso le due
tables non possono essere uguali. Inoltre
gestisce anche il caso in cui tab1 sia vuota
e tab2 no, che porterebbe a tornare true
poiché il loop viene skippato, e quello in
cui tab1 sia un sottoinsieme di tab2 poiché
si controllano solo gli indici della prima.
--]]
if table.getn(tab1) ~= table.getn(tab2) then
return false
end
 
for key, value in pairs(tab1) do
--[[
Stante la type safety di table.equal, è
più comodo fare così
--]]
if not table.equal(value, tab2[key]) then
return false
end
end
 
return true
--[[
Se il numero di elementi è diverso le due
tables non possono essere uguali. Inoltre
gestisce anche il caso in cui tab1 sia vuota
e tab2 no, che porterebbe a tornare true
poiché il loop viene skippato, e quello in
cui tab1 sia un sottoinsieme di tab2 poiché
si controllano solo gli indici della prima.
--]]
if table.getn(tab1) ~= table.getn(tab2) then
return false
end
for key, value in pairs(tab1) do
--[[
Stante la type safety di table.equal, è
più comodo fare così
--]]
if not table.equal(value, tab2[key]) then
return false
end
end
return true
end
 
table.eq = table.equal
t.equal, t.eq = table.qualequal, table.equal
 
--[[
table.merge = function(tab1, tab2)
 
local dest = mw.clone(tab1)
 
--[[
È necessario il doppio ciclo per avere
le chiavi intere in ordine
--]]
for key_, value in ipairs(tab2) do
table.insert(dest, value)
end
for key, value in table.nonIntPairs(tab2) do
dest[key] = value
end
return dest
end
 
table.recursiveMerge = function(tab1, tab2)
 
local dest = mw.clone(tab1)
--[[
È necessario il doppio ciclo per avere
le chiavi intere in ordine
--]]
for key_, value in ipairs(tab2) do
table.insert(dest, value)
end
for key, value in table.nonIntPairs(tab2) do
if dest[key]
and type(dest[key]) == 'table'
dest[key] = value
end
end
return dest
end
 
--]]
table.filter = function(tab, cond)
local dest = {}
--[[
È necessario il doppio ciclo per avere
le chiavi intere in ordine
--]]
for key, value in ipairs(tab) do
if cond(value, key) then
table.insert(dest, value)
end
end
for key, value in table.nonIntPairs(tab) do
if cond(value, key) then
dest[key] = value
end
end
return dest
end
 
--]]
table.flip = function(tab)
local flipped = {}
for key, value in pairs(tab) do
flipped[value] = key
end
return flipped
end
 
--]]
table.noDuplicates = function(tab)
local check, n = {}, 1
 
--[[
Il doppio ciclo si rende necessario per
mantenere l'ordine delle chiavi numeriche.
La variabile n serve per non avere buchi.
Non si usa minor poiché le chiavi vengono
già tornate in ordine crescente da ipairs.
--]]
for _, value in ipairs(tab) do
if not check[value] then
check[value] = n
n = n + 1
end
end
 
for key, value in table.nonIntPairs(tab) do
if minor(key, check[value]) then
check[value] = key
end
end
 
return table.flip(check)
--[[
Il doppio ciclo si rende necessario per
mantenere l'ordine delle chiavi numeriche.
La variabile n serve per non avere buchi.
Non si usa minor poiché le chiavi vengono
già tornate in ordine crescente da ipairs.
--]]
for key, value in ipairs(tab) do
if not check[value] then
check[value] = n
n = n + 1
end
end
for key, value in table.nonIntPairs(tab) do
if minor(key, check[value]) then
check[value] = key
end
end
return table.flip(check)
end
 
table.no_duplicates, table.unique =
table.noDuplicates, table.noDuplicates
t.noDuplicates, t.no_duplicates, t.unique =
table.noDuplicates, table.noDuplicates, table.noDuplicates
 
--[[
--]]
table.keys = function(tab)
local keys = {}
for key in pairs(tab) do
table.insert(keys, key)
end
return keys
end
 
--]]
table.cloneLoadData = function(value)
return table.map(value, function(v)
if (type(v) == 'table') then
return table.cloneLoadData(v)
else
-- if v isn't a table, is a bool, num or string
return v
end
end)
end
 
table.clone_load_data = table.cloneLoadData
t.cloneLoadData, t.clone_load_data =
table.cloneLoadData , table.cloneLoadData
 
return t