Module:Enum
Module documentation
This documentation is transcluded from Module:Enum/doc. [edit] [purge]
Module:Enum requires Module:LibraryUtil.
Module:Enum requires Module:Logger.
Module:Enum is required by Module:DependencyList.
This module is a helper module to be used by other modules; it may not designed to be invoked directly. See GSWiki:Lua/Helper modules for a full list and more information. For a full list of modules using this helper click here
| Module | Function | Type | Use | Example |
|---|---|---|---|---|
| Enum | all( enum, [fn], [clone|false] ) | table, function/nil, boolean/nil | Loops over the array part of enum and passes each element as the first argument to fn. If fn returns true for all elements then all() returns true, otherwise false. If no function is given function( item ) return item end is used. | |
any( enum, [fn], [clone|false] ) | table, function/nil, boolean/nil | Loops over the array part of enum and passes each element as the first argument to fn. If fn returns true for at least one element then any() returns true, otherwise false. If no function is given function( item ) return item end is used. If clone is true the input enum is deep copied using mw.clone() before use. | ||
contains( enum, elem, [clone|false] ) | table, any, boolean/nil | Returns true if enum contains elem, otherwise returns false. | ||
each( enum, fn, [clone|false] ) | table, function, boolean/nil | Loops over the array part of enum and passes each element as the first argument to fn. This function returns nothing. | ||
filter( enum, [fn], [clone|false] ) | table, function/nil, boolean/nil | Loops over the array part of enum and passes each element as the first argument to fn. If fn returns true the corresponding element is copied to a new table which is then returned. If no function is given function( item ) return item end is used. | ||
find( enum, fn, [default|nil], [clone|false] ) | table, function, any, boolean/nil | Loops over the array part of enum and passes each element as the first argument to fn. The first element where fn returns true is returned. If no elements passes the test, default is returned. | ||
find_index( enum, fn, [default|nil], [clone|false] ) | table, function, any, boolean/nil | Loops over the array part of enum and passes each element as the first argument to fn. The index of the first element where fn returns true is returned. If no elements passes the test, default is returned. | ||
insert( enum1, enum2, [index|#enum1+1], [clone|false] ) | table, table, number, boolean/nil | Returns a new table with enum2 inserted into enum1 at index index. If no index is given, enum2 is appended to enum1. | ||
intersect( enum1, enum2, [clone|false] ) | table, table, boolean/nil | Returns a table containing elements which exist in both enums. The order of the elements is the same as the order they occure in enum1. | ||
intersects( enum1, enum2, [clone|false] ) | table, table, boolean/nil | Returns true if both sets have at least one element with equal values. | ||
map( enum, fn, [clone|false] ) | table, function, boolean/nil | Loops over the array part of enum and passes each element as the first argument to fn. The return value of fn is appended to a new table. This new table is returned. | ||
max_by( enum, fn, [clone|false] ) | table, function, boolean/nil | Loops over the array part of enum and passes each element as the first argument to fn. max_by() returns two values, the first is the element where fn returned the largest value, the second is this largest value. The > operator is used for the comparisons. | ||
new( [enum|{}] ) | table | Adds a metatable to enum which allows it use elementwise math operations on the table. Also makes it possible to use the colon : operator with all the other functions listed here that take a table as their first argument.
local t = enum.new{1, 2, 3}
local t2 = enum{4, 5, 6} -- Alternative notation
mw.log( -t ) --> { -1, -2, -3 }
mw.log( t + 2 ) --> { 3, 4, 5 }
mw.log( t - 2 ) --> { -1, 0, 1 }
mw.log( t * 2 ) --> { 2, 4, 6 }
mw.log( t / 2 ) --> { 0.5, 1, 1.5 }
mw.log( t ^ 2 ) --> { 1, 4, 9 }
mw.log( t + t2 ) --> { 5, 7, 9 }
mw.log( t .. t2 ) --> { 1, 2, 3, 4, 5, 6 }
mw.log( t:sum() ) --> 6
mw.log( (t .. t2):reject{3, 4, 5} ) --> { 1, 2, 6 }
| ||
newIncrementor( [start|1], [step|1] ) | number, number | Returns a new incrementor function. Every time this incrementor function is called it returns a number step higher than the previous call. The current value can be obtained with inc.n or set inc.n = number where inc is an incrementor function. The step size can be changed with inc.step = number. | ||
range( stop )range( start, stop, [step|1] ) | number, number, number | Returns a table containing a sequence of numbers from start to stop (both inclusive if ints, end-exclusive if floats) by step. range(4) produces {1, 2, 3, 4} (start defaults to 1). range(0, 4) produces {0, 1, 2, 3, 4}. When step is given, it specifies the increment (or decrement). | ||
reduce( enum, fn, [accumulator|enum[1]], [clone|false] ) | table, function, any, boolean/nil | Loops over the array part of enum and passes each element as the first argument and accumulator as the second to fn. The return value of fn becomes the new accumulator. The final value of accumulator is returned. If no accumulator is given then the first element in enum is used. | ||
reject( enum, [fn], [clone|false] )reject( enum, [table], [clone|false] ) | table, function/table, boolean/nil | The opposite of filter(). If the second argument is a table, every element in enum equal to any of the values in this table will be rejected. | ||
rep( val, n, [clone|false] ) | any, number, boolean | Returns a table with n copies of val. | ||
scan( enum, fn, [accumulator|enum[1]], [clone|false] ) | table, function, any, boolean/nil | Same as reduce() but each step is appended to a table. This table is then returned. | ||
slice( enum, [start|1], [stop|#enum], [clone|false] ) | table, number/nil, number/nil, boolean/nil | Returns a table containing all the elements of enum between the start and stop indices. The start and stop indices are inclusive. | ||
split( enum, count, [clone|false] ) | table, number, boolean/nil | Returns two tables where the first is equivalent to slice( enum, 1, count ) and the second slice( enum, count+1, #enum ). | ||
sum( enum, [clone|false] ) | table, boolean/nil | Returns the sum of all array elements in enum. | ||
take( enum, count, [clone|false] ) | table, number, boolean/nil | Returns only the first table of split( enum, count ). | ||
take_every( enum, n, [clone|false] ) | table, number, boolean/nil | Returns a table containing every nth element of enum. | ||
unique( enum, [fn], [clone|false] ) | table, function/nil, boolean/nil | Returns a new table where all duplicate values in enum are removed. In case a duplicate is present, the element with the lowest index will be kept and every subsequent duplicate element is removed. fn can be used to create a custom id for every element so that the result is a table with elements which all create a unique id. If no function is given function( item ) return item end is used. | ||
zip( enums, [clone|false] ) | table, boolean/nil | Groups elements with the same indexes from different arrays together, i.e. zip{ {a1, a2, a3}, {b1, b2, b3}, {c1, c2} } -> {{a1, b1, c1}, {a2, b2, c2}, {a3, b3}} |
-- <nowiki> awawa
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti
local p = {}
p.__index = p
setmetatable(p, {
__call = function(_, enum)
return p.new(enum)
end
})
function p.__tostring(enum)
local dumpObject = require('Module:Logger').dumpObject
setmetatable(enum, nil)
return dumpObject(enum, {clean=true, collapseLimit=100})
end
function p.__concat(lhs, rhs)
if type(lhs) == 'table' and type(rhs) == 'table' then
return p.insert(lhs, rhs)
else
return tostring(lhs) .. tostring(rhs)
end
end
function p.__unm(enum)
return p.map(enum, function(x) return -x end)
end
local function mathTemplate(lhs, rhs, funName, fun)
checkTypeMulti('Module:Enum.' .. funName, 1, lhs, {'number', 'table'})
checkTypeMulti('Module:Enum.' .. funName, 2, rhs, {'number', 'table'})
local res = setmetatable({}, getmetatable(lhs) or getmetatable(rhs))
if type(lhs) == 'number' or type(rhs) == 'number' then
local scalar, vector
if type(lhs) == 'number' then
scalar = lhs
vector = rhs
else
scalar = rhs
vector = lhs
end
for i = 1, #vector do
res[i] = fun(vector[i], scalar)
end
else
assert(#lhs == #rhs, 'Tables are not equal length')
for i = 1, #lhs do
res[i] = fun(lhs[i], rhs[i])
end
end
return res
end
function p.__add(lhs, rhs)
return mathTemplate(lhs, rhs, '__add', function(x, y) return x + y end)
end
function p.__sub(lhs, rhs)
return mathTemplate(lhs, rhs, '__sub', function(x, y) return x - y end)
end
function p.__mul(lhs, rhs)
return mathTemplate(lhs, rhs, '__mul', function(x, y) return x * y end)
end
function p.__div(lhs, rhs)
return mathTemplate(lhs, rhs, '__div', function(x, y) return x / y end)
end
function p.__pow(lhs, rhs)
return mathTemplate(lhs, rhs, '__pow', function(x, y) return x ^ y end)
end
function p.__lt(lhs, rhs)
for i = 1, math.min(#lhs, #rhs) do
if lhs[i] >= rhs[i] then
return false
end
end
return true
end
function p.__le(lhs, rhs)
for i = 1, math.min(#lhs, #rhs) do
if lhs[i] > rhs[i] then
return false
end
end
return true
end
function p.__eq(lhs, rhs)
if #lhs ~= #rhs then
return false
end
for i = 1, #lhs do
if lhs[i] ~= rhs[i] then
return false
end
end
return true
end
function p.all(enum, fn, clone)
checkType('Module:Enum.all', 1, enum, 'table')
checkType('Module:Enum.all', 2, fn, 'function', true)
checkType('Module:Enum.all', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
local i = 1
while enum[i] ~= nil do
if not fn(enum[i], i) then
return false
end
i = i + 1
end
return true
end
function p.any(enum, fn, clone)
checkType('Module:Enum.any', 1, enum, 'table')
checkType('Module:Enum.any', 2, fn, 'function', true)
checkType('Module:Enum.any', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
local i = 1
while enum[i] ~= nil do
if fn(enum[i], i) then
return true
end
i = i + 1
end
return false
end
function p.contains(enum, elem, clone)
checkType('Module:Enum.contains', 1, enum, 'table')
checkType('Module:Enum.contains', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum); elem = mw.clone(elem) end
return p.any(enum, function(item) return item == elem end)
end
function p.each(enum, fn, clone)
checkType('Module:Enum.each', 1, enum, 'table')
checkType('Module:Enum.each', 2, fn, 'function')
checkType('Module:Enum.each', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
local i = 1
while enum[i] ~= nil do
fn(enum[i], i)
i = i + 1
end
end
function p.filter(enum, fn, clone)
checkType('Module:Enum.filter', 1, enum, 'table')
checkType('Module:Enum.filter', 2, fn, 'function', true)
checkType('Module:Enum.filter', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
local r = setmetatable({}, getmetatable(enum))
local len = 0
local i = 1
while enum[i] ~= nil do
if fn(enum[i], i) then
len = len + 1
r[len] = enum[i]
end
i = i + 1
end
return r
end
function p.find(enum, fn, default, clone)
checkType('Module:Enum.find', 1, enum, 'table')
checkType('Module:Enum.find', 2, fn, 'function')
checkType('Module:Enum.find', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum); default = mw.clone(default) end
local i = 1
while enum[i] ~= nil do
if fn(enum[i], i) then
return enum[i], i
end
i = i + 1
end
return default
end
function p.find_index(enum, fn, default, clone)
checkType('Module:Enum.find_index', 1, enum, 'table')
checkType('Module:Enum.find_index', 2, fn, 'function')
checkType('Module:Enum.find_index', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum); default = mw.clone(default) end
fn = fn or function(item) return item end
local i = 1
while enum[i] ~= nil do
if fn(enum[i], i) then
return i
end
i = i + 1
end
return default
end
function p.newIncrementor(start, step)
checkType('Module:Enum.newIncrementor', 1, start, 'number', true)
checkType('Module:Enum.newIncrementor', 2, step, 'number', true)
step = step or 1
local n = (start or 1) - step
local obj = {}
return setmetatable(obj, {
__call = function() n = n + step return n end,
__tostring = function() return n end,
__index = function() return n end,
__newindex = function(self, k, v)
if k == 'step' and type(v) == 'number' then
step = v
elseif type(v) == 'number' then
n = v
end
end,
__concat = function(x, y) return tostring(x) .. tostring(y) end
})
end
function p.intersect(enum1, enum2, clone)
checkType('Module:Enum.intersect', 1, enum1, 'table')
checkType('Module:Enum.intersect', 2, enum2, 'table')
checkType('Module:Enum.intersect', 3, clone, 'boolean', true)
if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
local enum2Elements = {}
local res = setmetatable({}, getmetatable(enum1) or getmetatable(enum2))
local len = 0
p.each(enum2, function(item) enum2Elements[item] = true end)
p.each(enum1, function(item)
if enum2Elements[item] then
len = len + 1
res[len] = item
end
end)
return res
end
function p.intersects(enum1, enum2, clone)
checkType('Module:Enum.intersects', 1, enum1, 'table')
checkType('Module:Enum.intersects', 2, enum2, 'table')
checkType('Module:Enum.intersects', 3, clone, 'boolean', true)
if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
local small = {}
local large
if #enum1 <= #enum2 then
p.each(enum1, function(item) small[item] = true end)
large = enum2
else
p.each(enum2, function(item) small[item] = true end)
large = enum1
end
return p.any(large, function(item) return small[item] end)
end
function p.insert(enum1, enum2, index, clone)
checkType('Module:Enum.insert', 1, enum1, 'table')
checkType('Module:Enum.insert', 2, enum2, 'table')
checkType('Module:Enum.insert', 3, index, 'number', true)
checkType('Module:Enum.insert', 4, clone, 'boolean', true)
if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end
local len1 = #enum1
local len2 = #enum2
index = index or (len1 + 1)
local res = setmetatable({}, getmetatable(enum1) or getmetatable(enum2))
for i = 1, (len1 + len2) do
if i < index then
res[i] = enum1[i]
elseif i < (index + len2) then
res[i] = enum2[i - index + 1]
else
res[i] = enum1[i - len2]
end
end
return res
end
function p.map(enum, fn, clone)
checkType('Module:Enum.map', 1, enum, 'table')
checkType('Module:Enum.map', 2, fn, 'function')
checkType('Module:Enum.map', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
local len = 0
local r = setmetatable({}, getmetatable(enum))
local i = 1
while enum[i] ~= nil do
local tmp = fn(enum[i], i)
if tmp ~= nil then
len = len + 1
r[len] = tmp
end
i = i + 1
end
return r
end
function p.max_by(enum, fn, clone)
checkType('Module:Enum.max_by', 1, enum, 'table')
checkType('Module:Enum.max_by', 2, fn, 'function')
checkType('Module:Enum.max_by', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
return unpack(p.reduce(enum, function(new, old)
local y = fn(new)
return y > old[2] and {new, y} or old
end, {enum[1], -math.huge}))
end
function p.new(enum)
for _, v in pairs(enum) do
if type(v) == 'table' then
p.new(v)
end
end
if getmetatable(enum) == nil then
setmetatable(enum, p)
end
return enum
end
function p.range(start, stop, step)
checkType('Module:Enum.range', 1, start, 'number')
checkType('Module:Enum.range', 2, stop, 'number', true)
checkType('Module:Enum.range', 3, step, 'number', true)
local array = setmetatable({}, p)
local len = 0
if not stop then
stop = start
start = 1
end
for i = start, stop, step or 1 do
len = len + 1
array[len] = i
end
return array
end
function p.reduce(enum, fn, accumulator, clone)
checkType('Module:Enum.reduce', 1, enum, 'table')
checkType('Module:Enum.reduce', 2, fn, 'function')
checkType('Module:Enum.reduce', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end
local acc = accumulator
local i = 1
while enum[i] ~= nil do
if i == 1 and not accumulator then
acc = enum[i]
else
acc = fn(enum[i], acc)
end
i = i + 1
end
return acc
end
function p.reject(enum, fn, clone)
checkType('Module:Enum.reject', 1, enum, 'table')
checkTypeMulti('Module:Enum.reject', 2, fn, {'function', 'table', 'nil'})
checkType('Module:Enum.reject', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
local r = setmetatable({}, getmetatable(enum))
local len = 0
if type(fn) == 'function' then
local i = 1
while enum[i] ~= nil do
if not fn(enum[i], i) then
len = len + 1
r[len] = enum[i]
end
i = i + 1
end
else
local rejectMap = {}
p.each(fn, function(item) rejectMap[item] = true end)
local i = 1
while enum[i] ~= nil do
if not rejectMap[enum[i]] then
len = len + 1
r[len] = enum[i]
end
i = i + 1
end
end
return r
end
function p.rep(val, n, clone)
checkType('Module:Enum.rep', 2, n, 'number')
checkType('Module:Enum.reject', 3, clone, 'boolean', true)
if clone then val = mw.clone(val) end
local r = setmetatable({}, p)
for i = 1, n do
r[i] = val
end
return r
end
function p.scan(enum, fn, accumulator, clone)
checkType('Module:Enum.scan', 1, enum, 'table')
checkType('Module:Enum.scan', 2, fn, 'function')
checkType('Module:Enum.scan', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end
local acc = accumulator
local r = setmetatable({}, getmetatable(enum))
local i = 1
while enum[i] ~= nil do
if i == 1 and not accumulator then
acc = enum[i]
else
acc = fn(enum[i], acc)
end
r[i] = acc
i = i + 1
end
return r
end
function p.slice(enum, start, finish, clone)
checkType('Module:Enum.slice', 1, enum, 'table')
checkType('Module:Enum.slice', 2, start, 'number', true)
checkType('Module:Enum.slice', 3, finish, 'number', true)
checkType('Module:Enum.slice', 4, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
start = start or 1
finish = finish or #enum
local r = setmetatable({}, getmetatable(enum))
local len = 0
for i = start, finish do
len = len + 1
r[len] = enum[i]
end
return r
end
function p.split(enum, count, clone)
checkType('Module:Enum.split', 1, enum, 'table')
checkType('Module:Enum.split', 2, count, 'number')
checkType('Module:Enum.split', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
if #enum < count then
return enum, {}
elseif count < 1 then
return {}, enum
end
local x = setmetatable({}, getmetatable(enum))
local y = setmetatable({}, getmetatable(enum))
for i = 1, #enum do
table.insert(i <= count and x or y, enum[i])
end
return x, y
end
function p.sum(enum, clone)
checkType('Module:Enum.sum', 1, enum, 'table')
checkType('Module:Enum.sum', 2, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
return p.reduce(enum, function(x, y) return x + y end)
end
function p.take(enum, count, clone)
checkType('Module:Enum.take', 1, enum, 'table')
checkType('Module:Enum.take', 2, count, 'number')
checkType('Module:Enum.take', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
local x, _ = p.split(enum, count)
return x
end
function p.take_every(enum, n, clone)
checkType('Module:Enum.take_every', 1, enum, 'table')
checkType('Module:Enum.take_every', 2, n, 'number')
checkType('Module:Enum.take_every', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
local r = setmetatable({}, getmetatable(enum))
local len = 0
local i = 1
while enum[i] ~= nil do
if (i - 1) % n == 0 then
len = len + 1
r[len] = enum[i]
end
i = i + 1
end
return r
end
function p.unique(enum, fn, clone)
checkType('Module:Enum.unique', 1, enum, 'table')
checkType('Module:Enum.unique', 2, fn, 'function', true)
checkType('Module:Enum.unique', 3, clone, 'boolean', true)
if clone then enum = mw.clone(enum) end
fn = fn or function(item) return item end
local r = setmetatable({}, getmetatable(enum))
local len = 0
local hash = {}
local i = 1
while enum[i] ~= nil do
local id = fn(enum[i])
if not hash[id] then
len = len + 1
r[len] = enum[i]
hash[id] = true
end
i = i + 1
end
return r
end
function p.zip(enums, clone)
checkType('Module:Enum.zip', 1, enums, 'table')
checkType('Module:Enum.zip', 2, clone, 'boolean', true)
if clone then enums = mw.clone(enums) end
local r = setmetatable({}, getmetatable(enums))
local _, longest = p.max_by(enums, function(enum) return #enum end)
for i = 1, longest do
local q = {}
for j = 1, #enums do
table.insert(q, enums[j][i])
end
table.insert(r, q)
end
return r
end
return p
-- </nowiki>