| Latest revision |
Your text |
| Line 1: |
Line 1: |
| | -- <nowiki> awawa |
| local libraryUtil = require('libraryUtil') | | local libraryUtil = require('libraryUtil') |
| local checkType = libraryUtil.checkType | | local p = {} |
| local checkTypeMulti = libraryUtil.checkTypeMulti
| |
|
| |
|
| ---Returns the length of the array but it also works on proxy arrays
| | function p.any(enum, fn, clone) |
| ---@param arr any[]
| | libraryUtil.checkType('Module:Enum.any', 1, enum, 'table') |
| ---@return integer
| | libraryUtil.checkType('Module:Enum.any', 2, fn, 'function', true) |
| local function len(arr)
| | libraryUtil.checkType('Module:Enum.any', 3, clone, 'boolean', true) |
| local l = #arr | | if clone then enum = mw.clone(enum) end |
| if l == 0 then
| | fn = fn or function(item) return item end |
| if arr[1] ~= nil then
| | for _, item in ipairs(enum) do |
| -- Exponential search to find length of proxy table
| | if fn(item) then |
| local low = 1
| | return true |
| local high = 1
| |
| local ceil = math.ceil
| |
| while arr[high] ~= nil do
| |
| high = high * 2
| |
| end
| |
| while low ~= high do
| |
| local m = ceil((low + high) / 2)
| |
| if arr[m] == nil then
| |
| high = m - 1
| |
| else
| |
| low = m
| |
| end
| |
| end
| |
| return low
| |
| else | |
| return 0 | |
| end | | end |
| else
| |
| return l
| |
| end | | end |
| | return false |
| end | | end |
|
| |
|
| ---@class Array
| | function p.all(enum, fn, clone) |
| ---@operator call(any[]): Array
| | libraryUtil.checkType('Module:Enum.all', 1, enum, 'table') |
| ---@operator concat(any[]): Array
| | libraryUtil.checkType('Module:Enum.all', 2, fn, 'function', true) |
| ---@operator concat(number|string|function): string
| | libraryUtil.checkType('Module:Enum.all', 3, clone, 'boolean', true) |
| ---@operator unm: Array
| | if clone then enum = mw.clone(enum) end |
| ---@operator add(number|number[]|Array): Array
| | fn = fn or function(item) return item end |
| ---@operator sub(number|number[]|Array): Array
| | for _, item in ipairs(enum) do |
| ---@operator mul(number|number[]|Array): Array
| | if not fn(item) then |
| ---@operator div(number|number[]|Array): Array
| |
| ---@operator pow(number|number[]|Array): Array
| |
| local Array = {
| |
| pop = table.remove,
| |
| len = len
| |
| }
| |
| Array.__index = Array
| |
| | |
| setmetatable(Array, {
| |
| __index = table,
| |
| __call = function (_, arr)
| |
| return Array.new(arr)
| |
| end | |
| })
| |
| | |
| function Array.__concat(lhs, rhs)
| |
| if type(lhs) == 'table' and type(rhs) == 'table' then
| |
| local res = {}
| |
| local l1 = len(lhs)
| |
| for i = 1, l1 do
| |
| res[i] = lhs[i]
| |
| end
| |
| for i = 1, len(rhs) do
| |
| res[l1 + i] = rhs[i]
| |
| end
| |
| return setmetatable(res, getmetatable(lhs) or getmetatable(rhs))
| |
| else
| |
| return tostring(lhs) .. tostring(rhs)
| |
| end
| |
| end
| |
| | |
| function Array.__unm(arr)
| |
| return Array.map(arr, function(x) return -x end)
| |
| end
| |
| | |
| ---@param lhs number|number[]|Array
| |
| ---@param rhs number|number[]|Array
| |
| ---@param funName string
| |
| ---@param opName string
| |
| ---@param fun fun(lhs: number, rhs: number): number
| |
| ---@return Array
| |
| local function mathTemplate(lhs, rhs, funName, opName, fun)
| |
| checkTypeMulti('Module:Array.' .. funName, 1, lhs, {'number', 'table'})
| |
| checkTypeMulti('Module:Array.' .. funName, 2, rhs, {'number', 'table'}) | |
| local res = {}
| |
| | |
| if type(lhs) == 'number' then
| |
| for i = 1, len(rhs) do
| |
| res[i] = fun(lhs, rhs[i])
| |
| end
| |
| elseif type(rhs) == 'number' then
| |
| for i = 1, len(lhs) do
| |
| res[i] = fun(lhs[i], rhs)
| |
| end
| |
| else | |
| assert(len(lhs) == len(rhs), string.format('Elementwise %s failed because arrays have different sizes (left: %d, right: %d)', opName, len(lhs), len(rhs)))
| |
| for i = 1, len(lhs) do
| |
| res[i] = fun(lhs[i], rhs[i])
| |
| end
| |
| end
| |
| | |
| return setmetatable(res, getmetatable(lhs) or getmetatable(rhs))
| |
| end
| |
| | |
| function Array.__add(lhs, rhs)
| |
| return mathTemplate(lhs, rhs, '__add', 'addition', function(x, y) return x + y end)
| |
| end
| |
| | |
| function Array.__sub(lhs, rhs)
| |
| return mathTemplate(lhs, rhs, '__sub', 'substraction', function(x, y) return x - y end)
| |
| end
| |
| | |
| function Array.__mul(lhs, rhs)
| |
| return mathTemplate(lhs, rhs, '__mul', 'multiplication', function(x, y) return x * y end) | |
| end
| |
| | |
| function Array.__div(lhs, rhs)
| |
| return mathTemplate(lhs, rhs, '__div', 'division', function(x, y) return x / y end)
| |
| end | |
| | |
| function Array.__pow(lhs, rhs)
| |
| return mathTemplate(lhs, rhs, '__pow', 'exponentiation', function(x, y) return x ^ y end) | |
| end
| |
| | |
| function Array.__eq(lhs, rhs)
| |
| if len(lhs) ~= len(rhs) then
| |
| return false
| |
| end
| |
| for i = 1, len(lhs) do | |
| if lhs[i] ~= rhs[i] then | |
| return false | | return false |
| end | | end |
| Line 138: |
Line 31: |
| end | | end |
|
| |
|
| ---Behaviour depends on the value of `fn`:
| | function p.each(enum, fn, clone) |
| ---* `nil` - Checks that the array doesn't contain any **false** elements.
| | libraryUtil.checkType('Module:Enum.each', 1, enum, 'table') |
| ---* `fun(elem: any, i?: integer): boolean` - Returns **true** if `fn` returns **true** for every element.
| | libraryUtil.checkType('Module:Enum.each', 2, fn, 'function') |
| ---* `number` | `table` | `boolean` - Checks that all elements in `arr` are equal to this value.
| | libraryUtil.checkType('Module:Enum.each', 3, clone, 'boolean', true) |
| ---@param arr any[]
| | if clone then enum = mw.clone(enum) end |
| ---@param fn? any
| | for _, item in ipairs(enum) do |
| ---@return boolean
| | fn(item) |
| function Array.all(arr, fn)
| |
| checkType('Module:Array.all', 1, arr, 'table') | |
| if fn == nil then fn = function(item) return item end end | |
| if type(fn) ~= 'function' then | |
| local val = fn
| |
| fn = function(item) return item == val end | |
| end | | end |
| for i = 1, len(arr) do
| |
| ---@diagnostic disable-next-line: redundant-parameter
| |
| if not fn(arr[i], i) then
| |
| return false
| |
| end
| |
| end
| |
| return true
| |
| end | | end |
|
| |
|
| ---Behaviour depends on the value of `fn`:
| | function p.filter(enum, fn, clone) |
| ---* `nil` - Checks that the array contains at least one non **false** element.
| | libraryUtil.checkType('Module:Enum.filter', 1, enum, 'table') |
| ---* `fun(elem: any, i?: integer): boolean` - Returns **true** if `fn` returns **true** for at least one element.
| | libraryUtil.checkType('Module:Enum.filter', 2, fn, 'function', true) |
| ---* `number` | `table` | `boolean` - Checks that `arr` contains this value.
| | libraryUtil.checkType('Module:Enum.filter', 3, clone, 'boolean', true) |
| ---@param arr any[]
| | if clone then enum = mw.clone(enum) end |
| ---@param fn? any
| | fn = fn or function(item) return item end |
| ---@return boolean
| |
| function Array.any(arr, fn) | |
| checkType('Module:Array.any', 1, arr, 'table')
| |
| if fn == nil then fn = function(item) return item end end
| |
| if type(fn) ~= 'function' then | |
| local val = fn
| |
| fn = function(item) return item == val end
| |
| end
| |
| for i = 1, len(arr) do
| |
| ---@diagnostic disable-next-line: redundant-parameter
| |
| if fn(arr[i], i) then
| |
| return true
| |
| end
| |
| end
| |
| return false
| |
| end
| |
| | |
| ---Recursively removes all metatables.
| |
| ---@param arr any[]
| |
| ---@return any[]
| |
| function Array.clean(arr)
| |
| checkType('Module:Array.clean', 1, arr, 'table')
| |
| for i = 1, len(arr) do
| |
| if type(arr[i]) == 'table' then
| |
| Array.clean(arr[i])
| |
| end
| |
| end
| |
| setmetatable(arr, nil)
| |
| return arr
| |
| end
| |
| | |
| ---Make a copy of the input table. Preserves metatables.
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@param deep? boolean # Recursively clone subtables if **true**.
| |
| ---@return T
| |
| function Array.clone(arr, deep)
| |
| checkType('Module:Array.clone', 1, arr, 'table') | |
| checkType('Module:Array.clone', 2, deep, 'boolean', true)
| |
| local res = {} | |
| for i = 1, len(arr) do
| |
| if deep == true and type(arr[i]) == 'table' then
| |
| res[i] = Array.clone(arr[i], true)
| |
| else
| |
| res[i] = arr[i]
| |
| end
| |
| end
| |
| return setmetatable(res, getmetatable(arr))
| |
| end
| |
| | |
| ---Check if `arr` contains `val`.
| |
| ---@param arr any[]
| |
| ---@param val any
| |
| ---@return boolean
| |
| function Array.contains(arr, val)
| |
| checkType('Module:Array.contains', 1, arr, 'table')
| |
| for i = 1, len(arr) do
| |
| if arr[i] == val then
| |
| return true
| |
| end
| |
| end
| |
| return false
| |
| end
| |
| | |
| ---Check if `arr` contains any of the values in the table `t`.
| |
| ---@param arr any[]
| |
| ---@param t any[]
| |
| ---@return boolean
| |
| function Array.containsAny(arr, t)
| |
| checkType('Module:Array.containsAny', 1, arr, 'table')
| |
| checkType('Module:Array.containsAny', 2, t, 'table')
| |
| local lookupTbl = {}
| |
| for i = 1, len(t) do
| |
| lookupTbl[t[i]] = true
| |
| end
| |
| for i = 1, len(arr) do
| |
| if lookupTbl[arr[i]] then
| |
| return true
| |
| end
| |
| end
| |
| return false | |
| end
| |
| | |
| ---Check if `arr` contains all values in the table `t`.
| |
| ---@param arr any[]
| |
| ---@param t any[]
| |
| ---@return boolean
| |
| function Array.containsAll(arr, t)
| |
| checkType('Module:Array.containsAll', 1, arr, 'table')
| |
| checkType('Module:Array.containsAll', 2, t, 'table')
| |
| local lookupTbl = {}
| |
| local trueCount = 0
| |
| local l = len(t)
| |
| for i = 1, l do
| |
| lookupTbl[t[i]] = false
| |
| end
| |
| for i = 1, len(arr) do
| |
| if lookupTbl[arr[i]] == false then
| |
| lookupTbl[arr[i]] = true
| |
| trueCount = trueCount + 1
| |
| end
| |
| if trueCount == l then
| |
| return true
| |
| end
| |
| end
| |
| return false
| |
| end
| |
| | |
| ---Convolute two number arrays.
| |
| ---@generic T: number[]
| |
| ---@param x T
| |
| ---@param y T
| |
| ---@return T
| |
| function Array.convolve(x, y)
| |
| checkType('Module:Array.convolve', 1, x, 'table') | |
| checkType('Module:Array.convolve', 2, y, 'table')
| |
| local z = {}
| |
| local xLen, yLen = len(x), len(y)
| |
| for j = 1, (xLen + yLen - 1) do
| |
| local sum = 0
| |
| for k = math.max(1, j - yLen + 1), math.min(xLen, j) do
| |
| sum = sum + x[k] * y[j-k+1]
| |
| end
| |
| z[j] = sum
| |
| end
| |
| return setmetatable(z, getmetatable(x) or getmetatable(y))
| |
| end
| |
| | |
| ---Remove **nil** values from `arr` while preserving order.
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@return T
| |
| function Array.condenseSparse(arr)
| |
| checkType('Module:Array.condenseSparse', 1, arr, 'table')
| |
| local keys = {}
| |
| local res = {}
| |
| local l = 0
| |
| for k in pairs(arr) do
| |
| l = l + 1
| |
| keys[l] = k
| |
| end
| |
| table.sort(keys)
| |
| for i = 1, l do
| |
| res[i] = arr[keys[i]]
| |
| end
| |
| return setmetatable(res, getmetatable(arr))
| |
| end
| |
| | |
| ---Behaviour depends on value of `val`:
| |
| ---* `nil` - Counts the number of non **false** elements.
| |
| ---* `fun(elem: any): boolean` - Count the number of times the function returned **true**.
| |
| ---* `boolean` | `number` | `table` - Counts the number of times this value occurs in `arr`.
| |
| ---@param arr any[]
| |
| ---@param val? any
| |
| ---@return integer
| |
| function Array.count(arr, val)
| |
| checkType('Module:Array.count', 1, arr, 'table')
| |
| if val == nil then val = function(item) return item end end
| |
| if type(val) ~= 'function' then
| |
| local _val = val
| |
| val = function(item) return item == _val end
| |
| end
| |
| local count = 0
| |
| for i = 1, len(arr) do
| |
| if val(arr[i]) then
| |
| count = count + 1
| |
| end
| |
| end
| |
| return count
| |
| end
| |
| | |
| ---Differentiate the array
| |
| ---@generic T: number[]
| |
| ---@param arr T
| |
| ---@param order number? # Oder of the differentiation. Default is 1.
| |
| ---@return T # Length is `#arr - order`
| |
| function Array.diff(arr, order)
| |
| checkType('Module:Array.diff', 1, arr, 'table')
| |
| checkType('Module:Array.diff', 2, order, 'number', true)
| |
| local res = {}
| |
| for i = 1, len(arr) - 1 do
| |
| res[i] = arr[i+1] - arr[i]
| |
| end
| |
| if order and order > 1 then
| |
| return Array.diff(res, order - 1)
| |
| end
| |
| return setmetatable(res, getmetatable(arr))
| |
| end
| |
| | |
| ---Loops over `arr` and passes each element as the first argument to `fn`. This function returns nothing.
| |
| ---@param arr any[]
| |
| ---@param fn fun(elem: any, i?: integer)
| |
| function Array.each(arr, fn)
| |
| checkType('Module:Array.each', 1, arr, 'table')
| |
| checkType('Module:Array.each', 2, fn, 'function')
| |
| for i = 1, len(arr) do
| |
| fn(arr[i], i)
| |
| end
| |
| end
| |
| | |
| ---Makes a copy of `arr` with only elements for which `fn` returned **true**.
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@param fn fun(elem: any, i?: integer): boolean
| |
| ---@return T
| |
| function Array.filter(arr, fn)
| |
| checkType('Module:Array.filter', 1, arr, 'table')
| |
| checkType('Module:Array.filter', 2, fn, 'function')
| |
| local r = {} | | local r = {} |
| local l = 0
| | for _, item in ipairs(enum) do |
| for i = 1, len(arr) do | | if fn(item) then |
| if fn(arr[i], i) then | | table.insert(r, item) |
| l = l + 1 | |
| r[l] = arr[i]
| |
| end | | end |
| end | | end |
| return setmetatable(r, getmetatable(arr)) | | return r |
| end | | end |
|
| |
|
| ---Find the first elements for which `fn` returns **true**.
| | function p.find(enum, fn, default, clone) |
| ---@param arr any[]
| | libraryUtil.checkType('Module:Enum.find', 1, enum, 'table') |
| ---@param fn any # A value to look for or a function of the form `fun(elem: any, i?: integer): boolean`.
| | libraryUtil.checkType('Module:Enum.find', 2, fn, 'function') |
| ---@param default? any # Value to return if no element passes the test.
| | libraryUtil.checkType('Module:Enum.find', 4, clone, 'boolean', true) |
| ---@return any? elem # The first element that passed the test.
| | if clone then enum = mw.clone(enum); default = mw.clone(default) end |
| ---@return integer? i # The index of the item that passed the test.
| | for _, item in ipairs(enum) do |
| function Array.find(arr, fn, default)
| | if fn(item) then |
| checkType('Module:Array.find', 1, arr, 'table') | | return item |
| checkTypeMulti('Module:Array.find_index', 2, fn, {'function', 'table', 'number', 'boolean'}) | |
| if type(fn) ~= 'function' then | |
| local _val = fn
| |
| fn = function(item) return item == _val end
| |
| end
| |
| for i = 1, len(arr) do | |
| ---@diagnostic disable-next-line: redundant-parameter
| |
| if fn(arr[i], i) then | |
| return arr[i], i | |
| end | | end |
| end | | end |
| return default, nil | | return default |
| end | | end |
|
| |
|
| ---Find the index of `val`.
| | function p.find_index(enum, fn, default, clone) |
| ---@param arr any[]
| | libraryUtil.checkType('Module:Enum.find_index', 1, enum, 'table') |
| ---@param val any # A value to look for or a function of the form `fun(elem: any, i?: integer): boolean`.
| | libraryUtil.checkType('Module:Enum.find_index', 2, fn, 'function') |
| ---@param default? any # Value to return if no element passes the test.
| | libraryUtil.checkType('Module:Enum.find_index', 4, clone, 'boolean', true) |
| ---@return integer?
| | if clone then enum = mw.clone(enum); default = mw.clone(default) end |
| function Array.find_index(arr, val, default)
| | for index, item in ipairs(enum) do |
| checkType('Module:Array.find_index', 1, arr, 'table') | | if fn(item) then |
| checkTypeMulti('Module:Array.find_index', 2, val, {'function', 'table', 'number', 'boolean'}) | | return index |
| if type(val) ~= 'function' then | |
| local _val = val
| |
| val = function(item) return item == _val end
| |
| end
| |
| for i = 1, len(arr) do | |
| ---@diagnostic disable-next-line: redundant-parameter
| |
| if val(arr[i], i) then | |
| return i | |
| end | | end |
| end | | end |
| Line 429: |
Line 82: |
| end | | end |
|
| |
|
| ---Extracts a subset of `arr`.
| | function p.map(enum, fn, clone) |
| ---@generic T: any[]
| | libraryUtil.checkType('Module:Enum.map', 1, enum, 'table') |
| ---@param arr T
| | libraryUtil.checkType('Module:Enum.map', 2, fn, 'function') |
| ---@param indexes integer|integer[] # Indexes of the elements.
| | libraryUtil.checkType('Module:Enum.map', 3, clone, 'boolean', true) |
| ---@return T
| | if clone then enum = mw.clone(enum) end |
| function Array.get(arr, indexes) | | local r = {} |
| checkType('Module:Array.set', 1, arr, 'table') | | for _, item in ipairs(enum) do |
| checkTypeMulti('Module:Array.set', 2, indexes, {'table', 'number'}) | | local temp = fn(item) -- Only use first returned item |
| if type(indexes) == 'number' then | | table.insert(r, temp) |
| indexes = {indexes}
| |
| end
| |
| local res = {} | |
| for i = 1, len(indexes) do | |
| res[i] = arr[indexes[i]]
| |
| end | | end |
| return setmetatable(res, getmetatable(arr)) | | return r |
| end | | end |
|
| |
|
| ---Integrates the array. Effectively does $\left\{\sum^{n}_{start}{arr[n]} \,\Bigg|\, n \in [start, stop]\right\}$.
| | function p.max_by(enum, fn, clone) |
| ---@generic T: number[]
| | libraryUtil.checkType('Module:Enum.max_by', 1, enum, 'table') |
| ---@param arr T # number[]
| | libraryUtil.checkType('Module:Enum.max_by', 2, fn, 'function') |
| ---@param start? integer # Index where to start the summation. Defaults to 1.
| | libraryUtil.checkType('Module:Enum.max_by', 3, clone, 'boolean', true) |
| ---@param stop? integer # Index where to stop the summation. Defaults to #arr.
| | if clone then enum = mw.clone(enum) end |
| ---@return T
| | return unpack(p.reduce(enum, function(new, old) |
| function Array.int(arr, start, stop) | | local y = fn(new) |
| checkType('Module:Array.int', 1, arr, 'table') | | return y > old[2] and {new, y} or old |
| checkType('Module:Array.int', 2, start, 'number', true) | | end, {0, 0})) |
| checkType('Module:Array.int', 3, stop, 'number', true) | |
| local res = {} | |
| start = start or 1 | |
| stop = stop or len(arr)
| |
| res[1] = arr[start]
| |
| for i = 1, stop - start do
| |
| res[i+1] = res[i] + arr[start + i]
| |
| end | |
| return setmetatable(res, getmetatable(arr))
| |
| end | | end |
|
| |
|
| ---Returns an array with elements that are present in both tables.
| | function p.reduce(enum, fn, accumulator, clone) |
| ---@generic T: any[]
| | libraryUtil.checkType('Module:Enum.reduce', 1, enum, 'table') |
| ---@param arr1 T
| | libraryUtil.checkType('Module:Enum.reduce', 2, fn, 'function') |
| ---@param arr2 T
| | libraryUtil.checkType('Module:Enum.reduce', 4, clone, 'boolean', true) |
| ---@return T
| | if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end |
| function Array.intersect(arr1, arr2) | | local acc = accumulator |
| checkType('Module:Array.intersect', 1, arr1, 'table') | | for index, item in ipairs(enum) do |
| checkType('Module:Array.intersect', 2, arr2, 'table') | | if index == 1 and not accumulator then |
| local arr2Elements = {} | | acc = item |
| local res = {} | | else |
| local l = 0 | | acc = fn(item, acc) |
| Array.each(arr2, function(item) arr2Elements[item] = true end) | |
| Array.each(arr1, function(item)
| |
| if arr2Elements[item] then | |
| l = l + 1 | |
| res[l] = item | |
| end | | end |
| end)
| |
| return setmetatable(res, getmetatable(arr1) or getmetatable(arr2))
| |
| end
| |
|
| |
| ---Checks if the two inputs have at least one element in common.
| |
| ---@param arr1 any[]
| |
| ---@param arr2 any[]
| |
| ---@return boolean
| |
| function Array.intersects(arr1, arr2)
| |
| checkType('Module:Array.intersects', 1, arr1, 'table')
| |
| checkType('Module:Array.intersects', 2, arr2, 'table')
| |
| local small = {}
| |
| local large
| |
| if len(arr1) <= len(arr2) then
| |
| Array.each(arr1, function(item) small[item] = true end)
| |
| large = arr2
| |
| else
| |
| Array.each(arr2, function(item) small[item] = true end)
| |
| large = arr1
| |
| end | | end |
| return Array.any(large, function(item) return small[item] end) | | return acc |
| end | | end |
|
| |
|
| ---Inserts values into `arr`.
| | function p.reject(enum, fn, clone) |
| ---@generic T: any[]
| | libraryUtil.checkType('Module:Enum.reject', 1, enum, 'table') |
| ---@param arr T
| | libraryUtil.checkType('Module:Enum.reject', 2, fn, 'function') |
| ---@param val any # If `val` is an array and `unpackVal` is **true** then the individual elements of `val` are inserted.
| | libraryUtil.checkType('Module:Enum.reject', 3, clone, 'boolean', true) |
| ---@param index? integer # Location to start the insertion. Default is at the end of `arr`.
| | if clone then enum = mw.clone(enum) end |
| ---@param unpackVal? boolean # Default is **false**.
| | fn = fn or function(item) return item end |
| ---@return T
| |
| ---@overload fun(arr: T, val: any, unpackVal: boolean): T
| |
| function Array.insert(arr, val, index, unpackVal) | |
| checkType('Module:Array.insert', 1, arr, 'table') | |
| checkTypeMulti('Module:Array.insert', 3, index, {'number', 'boolean', 'nil'}) | |
| checkType('Module:Array.insert', 4, unpackVal, 'boolean', true) | |
| if type(index) == 'boolean' then | |
| unpackVal, index = index, nil
| |
| end
| |
| local l = len(arr)
| |
| index = index or (l + 1) | |
| local mt = getmetatable(arr)
| |
| setmetatable(arr, nil)
| |
| | |
| if unpackVal and type(val) == 'table' then
| |
| local l2 = len(val)
| |
| for i = 0, l - index do
| |
| arr[l + l2 - i] = arr[l - i]
| |
| end
| |
| for i = 0, l2 - 1 do
| |
| arr[index + i] = val[i + 1]
| |
| end
| |
| else
| |
| table.insert(arr, index, val)
| |
| end
| |
| | |
| return setmetatable(arr, mt)
| |
| end
| |
| | |
| ---Returns the last element of `arr`.
| |
| ---@param arr any[]
| |
| ---@param offset? integer
| |
| ---@return any
| |
| function Array.last(arr, offset) | |
| checkType('Module:Array.last', 1, arr, 'table')
| |
| checkType('Module:Array.last', 2, offset, 'number', true)
| |
| return arr[len(arr) + offset]
| |
| end | |
| | |
| ---Returns a new table were each element of `arr` is modified by `fn`.
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@param fn fun(elem: any, i?: integer): any # First argument is the current element, the second argument is the index of the current element.
| |
| ---@return T
| |
| function Array.map(arr, fn)
| |
| checkType('Module:Array.map', 1, arr, 'table')
| |
| checkType('Module:Array.map', 2, fn, 'function')
| |
| local l = 0
| |
| local r = {} | | local r = {} |
| for i = 1, len(arr) do | | for _, item in ipairs(enum) do |
| local tmp = fn(arr[i], i) | | if not fn(item) then |
| if tmp ~= nil then
| | table.insert(r, item) |
| l = l + 1 | |
| r[l] = tmp
| |
| end | | end |
| end | | end |
| return setmetatable(r, getmetatable(arr)) | | return r |
| end
| |
| | |
| ---Find the element for which `fn` returned the largest value.
| |
| ---@param arr any[]
| |
| ---@param fn fun(elem: any): any # The returned value needs to be comparable using the `<` operator.
| |
| ---@return any elem # The element with the largest `fn` value.
| |
| ---@return integer i # The index of this element.
| |
| function Array.max_by(arr, fn)
| |
| checkType('Module:Array.max_by', 1, arr, 'table')
| |
| checkType('Module:Array.max_by', 2, fn, 'function')
| |
| return unpack(Array.reduce(arr, function(new, old, i)
| |
| local y = fn(new)
| |
| return y > old[2] and {new, y, i} or old
| |
| end, {nil, -math.huge}))
| |
| end
| |
| | |
| ---Find the largest value in the array.
| |
| ---@param arr any[] # The values need to be comparable using the `<` operator.
| |
| ---@return any elem
| |
| ---@return integer i # The index of the largest value.
| |
| function Array.max(arr)
| |
| checkType('Module:Array.max', 1, arr, 'table')
| |
| local val, _, i = Array.max_by(arr, function(x) return x end)
| |
| return val, i
| |
| end
| |
| | |
| ---Find the smallest value in the array.
| |
| ---@param arr any[] # The values need to be comparable using the `<` operator.
| |
| ---@return any elem
| |
| ---@return integer i # The index of the smallest value.
| |
| function Array.min(arr)
| |
| checkType('Module:Array.min', 1, arr, 'table')
| |
| local val, _, i = Array.max_by(arr, function(x) return -x end)
| |
| return val, i
| |
| end | | end |
|
| |
|
| ---Turn the input table into an Array. This makes it possible to use the colon `:` operator to access the Array methods.
| | function p.range(start, stop, step) |
| ---
| | libraryUtil.checkType('Module:Enum.range', 1, start, 'number') |
| ---It also enables the use of math operators with the array.
| | libraryUtil.checkType('Module:Enum.range', 2, stop, 'number', true) |
| ---```
| | libraryUtil.checkType('Module:Enum.range', 3, step, 'number', true) |
| ---local x = arr.new{ 1, 2, 3 }
| | local array = {} |
| ---local y = arr{ 4, 5, 6 } -- Alternative notation
| |
| ---
| |
| ---print( -x ) --> { -1, -2, -3 }
| |
| ---print( x + 2 ) --> { 3, 4, 5 }
| |
| ---print( x - 2 ) --> { -1, 0, 1 }
| |
| ---print( x * 2 ) --> { 2, 4, 6 }
| |
| ---print( x / 2 ) --> { 0.5, 1, 1.5 }
| |
| ---print( x ^ 2 ) --> { 1, 4, 9 }
| |
| ---
| |
| ---print( x + y ) --> { 5, 7, 9 }
| |
| ---print( x .. y ) --> { 1, 2, 3, 4, 5, 6 }
| |
| ---print( (x .. y):reject{3, 4, 5} ) --> { 1, 2, 6 }
| |
| ---print( x:sum() ) --> 6
| |
| ---
| |
| ---print( x:update( {1, 3}, y:get{2, 3} * 2 ) ) --> { 10, 2, 12 }
| |
| ---```
| |
| ---@param arr? any[]
| |
| ---@return Array
| |
| function Array.new(arr)
| |
| local obj = arr or {}
| |
| for _, v in pairs(obj) do
| |
| if type(v) == 'table' then
| |
| Array.new(v)
| |
| end
| |
| end
| |
| | |
| if getmetatable(obj) == nil then
| |
| setmetatable(obj, Array)
| |
| end
| |
| | |
| return obj
| |
| end
| |
| | |
| ---Creates an object that returns a value that is `step` higher than the previous value each time it gets called.
| |
| ---
| |
| ---The stored value can be read without incrementing by reading the `val` field.
| |
| ---
| |
| ---A new stored value can be set through the `val` field.
| |
| ---
| |
| ---A new step size can be set through the `step` field.
| |
| ---```
| |
| ---local inc = arr.newIncrementor(10, 5)
| |
| ---print( inc() ) --> 10
| |
| ---print( inc() ) --> 15
| |
| ---print( inc.val ) --> 15
| |
| ---inc.val = 100
| |
| ---inc.step = 20
| |
| ---print( inc.val ) --> 100
| |
| ---print( inc() ) --> 120
| |
| ---```
| |
| ---@param start? number # Default is 1.
| |
| ---@param step? number # Default is 1.
| |
| ---@return Incrementor
| |
| function Array.newIncrementor(start, step)
| |
| checkType('Module:Array.newIncrementor', 1, start, 'number', true)
| |
| checkType('Module:Array.newIncrementor', 2, step, 'number', true)
| |
| step = step or 1
| |
| local n = (start or 1) - step
| |
| ---@class Incrementor
| |
| local obj = {}
| |
| return setmetatable(obj, {
| |
| __call = function() n = n + step return n end,
| |
| __tostring = function() return tostring(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
| |
| | |
| ---Returns a range of numbers.
| |
| ---@param start number # Start value inclusive.
| |
| ---@param stop number # Stop value inclusive for integers, exclusive for floats.
| |
| ---@param step? number # Default is 1.
| |
| ---@return Array
| |
| ---@overload fun(stop: number): Array
| |
| function Array.range(start, stop, step)
| |
| checkType('Module:Array.range', 1, start, 'number') | |
| checkType('Module:Array.range', 2, stop, 'number', true) | |
| checkType('Module:Array.range', 3, step, 'number', true) | |
| local arr = {} | |
| local len = 0
| |
| if not stop then | | if not stop then |
| stop = start | | stop = start |
| Line 703: |
Line 147: |
| end | | end |
| for i = start, stop, step or 1 do | | for i = start, stop, step or 1 do |
| len = len + 1 | | table.insert(array, i) |
| arr[len] = i
| |
| end | | end |
| return setmetatable(arr, Array) | | return array |
| end | | end |
|
| |
|
| ---Condenses the array into a single value.
| | function p.scan(enum, fn, accumulator, clone) |
| ---
| | libraryUtil.checkType('Module:Enum.scan', 1, enum, 'table') |
| ---For each element `fn` is called with the current element, the current accumulator, and the current element index. The returned value of `fn` becomes the accumulator for the next element.
| | libraryUtil.checkType('Module:Enum.scan', 2, fn, 'function') |
| ---
| | libraryUtil.checkType('Module:Enum.scan', 4, clone, 'boolean', true) |
| ---If no `accumulator` value is given at the start then the first element off `arr` becomes the accumulator and the iteration starts from the second element.
| | if clone then enum = mw.clone(enum); accumulator = mw.clone(accumulator) end |
| ---```
| |
| ---local t = { 1, 2, 3, 4 }
| |
| ---local sum = arr.reduce( t, function(elem, acc) return acc + elem end ) -- sum == 10
| |
| ---```
| |
| ---@param arr any[]
| |
| ---@param fn fun(elem: any, acc: any, i?: integer): any # The result of this function becomes the `acc` for the next element.
| |
| ---@param accumulator? any
| |
| ---@return any # This is the last accumulator value.
| |
| function Array.reduce(arr, fn, accumulator)
| |
| checkType('Module:Array.reduce', 1, arr, 'table') | |
| checkType('Module:Array.reduce', 2, fn, 'function') | |
| local acc = accumulator | | local acc = accumulator |
| local start = 1
| |
| if acc == nil then
| |
| acc = arr[1]
| |
| start = 2
| |
| end
| |
| for i = start, len(arr) do
| |
| acc = fn(arr[i], acc, i)
| |
| end
| |
| return acc
| |
| end
| |
|
| |
| ---Make a copy off `arr` with certain values removed.
| |
| ---
| |
| ---Behaviour for different values of `val`:
| |
| ---* `boolean` | `number` - Remove values equal to this.
| |
| ---* `table` - Remove all values in this table.
| |
| ---* `fun(elem: any, i?: integer): boolean` - Remove elements for which the functions returns **true**.
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@param val table|function|number|boolean
| |
| ---@return T
| |
| function Array.reject(arr, val)
| |
| checkType('Module:Array.reject', 1, arr, 'table')
| |
| checkTypeMulti('Module:Array.reject', 2, val, {'function', 'table', 'number', 'boolean'})
| |
| if type(val) ~= 'function' and type(val) ~= 'table' then
| |
| val = {val}
| |
| end
| |
| local r = {} | | local r = {} |
| local l = 0 | | for index, item in ipairs(enum) do |
| if type(val) == 'function' then
| | if index == 1 and not accumulator then |
| for i = 1, len(arr) do
| | acc = item |
| if not val(arr[i], i) then
| | else |
| l = l + 1
| | acc = fn(item, acc) |
| r[l] = arr[i]
| |
| end
| |
| end | |
| else
| |
| local rejectMap = {}
| |
| Array.each(val --[[@as any[] ]], function(item) rejectMap[item] = true end)
| |
| for i = 1, len(arr) do
| |
| if not rejectMap[arr[i]] then
| |
| l = l + 1
| |
| r[l] = arr[i]
| |
| end
| |
| end | | end |
| | table.insert(r, acc) |
| end | | end |
| return setmetatable(r, getmetatable(arr)) | | return r |
| end | | end |
|
| |
|
| ---Returns an Array with `val` repeated `n` times.
| | function p.slice(enum, start, finish, clone) |
| ---@param val any
| | libraryUtil.checkType('Module:Enum.slice', 1, enum, 'table') |
| ---@param n integer
| | libraryUtil.checkType('Module:Enum.slice', 2, start, 'number', true) |
| ---@return Array
| | libraryUtil.checkType('Module:Enum.slice', 3, finish, 'number', true) |
| function Array.rep(val, n) | | libraryUtil.checkType('Module:Enum.slice', 4, clone, 'boolean', true) |
| checkType('Module:Array.rep', 2, n, 'number') | | if clone then enum = mw.clone(enum) end |
| local r = {} | | start = start or 1 |
| for i = 1, n do
| | finish = finish or #enum |
| r[i] = val
| |
| end
| |
| return setmetatable(r, Array)
| |
| end
| |
| | |
| ---Condenses the array into a single value while saving every accumulator value.
| |
| ---
| |
| ---For each element `fn` is called with the current element, the current accumulator, and the current element index. The returned value of `fn` becomes the accumulator for the next element.
| |
| ---
| |
| ---If no `accumulator` value is given at the start then the first element off `arr` becomes the accumulator and the iteration starts from the second element.
| |
| ---```
| |
| ---local t = { 1, 2, 3, 4 }
| |
| ---local x = arr.scan( t, function(elem, acc) return acc + elem end ) -- x = { 1, 3, 6, 10 }
| |
| ---```
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@param fn fun(elem: any, acc: any, i?: integer): any # Returned value becomes the accumulator for the next element.
| |
| ---@param accumulator? any
| |
| ---@return T
| |
| function Array.scan(arr, fn, accumulator)
| |
| checkType('Module:Array.scan', 1, arr, 'table')
| |
| checkType('Module:Array.scan', 2, fn, 'function') | |
| local acc = accumulator | |
| local r = {} | | local r = {} |
| for i = 1, len(arr) do | | for index, item in ipairs(enum) do |
| if i == 1 and not accumulator then | | if index >= start and index <= finish then |
| acc = arr[i] | | table.insert(r, item) |
| else
| |
| acc = fn(arr[i], acc, i)
| |
| end | | end |
| r[i] = acc
| |
| end | | end |
| return setmetatable(r, getmetatable(arr)) | | return r |
| end | | end |
|
| |
|
| ---Update a range of index with a range of values.
| | function p.split(enum, count, clone) |
| ---
| | libraryUtil.checkType('Module:Enum.split', 1, enum, 'table') |
| ---If if only one value is given but multiple indexes than that value is set for all those indexes.
| | libraryUtil.checkType('Module:Enum.split', 2, count, 'number') |
| ---
| | libraryUtil.checkType('Module:Enum.split', 3, clone, 'boolean', true) |
| ---If `values` is a table then it must of the same length as `indexes`.
| | if clone then enum = mw.clone(enum) end |
| ---@generic T: any[]
| | if #enum < count then |
| ---@param arr T
| | return enum, {} |
| ---@param indexes integer|integer[]
| | elseif count < 1 then |
| ---@param values any|any[]
| | return {}, enum |
| ---@return T
| |
| function Array.set(arr, indexes, values) | |
| checkType('Module:Array.set', 1, arr, 'table') | |
| checkTypeMulti('Module:Array.set', 2, indexes, {'table', 'number'}) | |
| local mt = getmetatable(arr) | |
| setmetatable(arr, nil) | |
| if type(indexes) == 'number' then | |
| indexes = {indexes} | |
| end | | end |
| if type(values) == 'table' then
| |
| assert(len(indexes) == len(values), string.format("Module:Array.set: 'indexes' and 'values' arrays are not equal length (#indexes = %d, #values = %d)", len(indexes), len(values)))
| |
| for i = 1, len(indexes) do
| |
| arr[indexes[i]] = values[i]
| |
| end
| |
| else
| |
| for i = 1, len(indexes) do
| |
| arr[indexes[i]] = values
| |
| end
| |
| end
| |
| return setmetatable(arr, mt)
| |
| end
| |
|
| |
|
| ---Extract a subtable from `arr`.
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@param start integer # Start index. Use negative values to count form the end of the array.
| |
| ---@param stop integer # Stop index. Use negative values to count form the end of the array.
| |
| ---@return T
| |
| ---@overload fun(arr: T, stop: integer): T
| |
| function Array.slice(arr, start, stop)
| |
| checkType('Module:Array.slice', 1, arr, 'table')
| |
| checkType('Module:Array.slice', 2, start, 'number', true)
| |
| checkType('Module:Array.slice', 3, stop, 'number', true)
| |
| start = start or len(arr)
| |
| if start < 0 then
| |
| start = len(arr) + start
| |
| end
| |
| if stop == nil then
| |
| stop = start
| |
| start = 1
| |
| end
| |
| if stop < 0 then
| |
| stop = len(arr) + stop
| |
| end
| |
| local r = {}
| |
| local len = 0
| |
| for i = start, stop do
| |
| len = len + 1
| |
| r[len] = arr[i]
| |
| end
| |
| return setmetatable(r, getmetatable(arr))
| |
| end
| |
|
| |
| ---Split `arr` into two arrays.
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@param index integer # Index to split on.
| |
| ---@return T x # [1, index]
| |
| ---@return T y # [index + 1, #arr]
| |
| function Array.split(arr, index)
| |
| checkType('Module:Array.split', 1, arr, 'table')
| |
| checkType('Module:Array.split', 2, index, 'number')
| |
| local x = {} | | local x = {} |
| local y = {} | | local y = {} |
| for i = 1, len(arr) do | | |
| table.insert(i <= index and x or y, arr[i]) | | for i = 1, #enum do |
| | table.insert( |
| | i <= count and x or y, |
| | enum[i] |
| | ) |
| end | | end |
| return setmetatable(x, getmetatable(arr)), setmetatable(y, getmetatable(arr)) | | return x, y |
| end | | end |
|
| |
|
| ---Returns the sum of all elements of `arr`.
| | function p.sum(enum, clone) |
| ---@param arr number[]
| | libraryUtil.checkType('Module:Enum.sum', 1, enum, 'table') |
| ---@return number
| | libraryUtil.checkType('Module:Enum.sum', 2, clone, 'boolean', true) |
| function Array.sum(arr) | | if clone then enum = mw.clone(enum) end |
| checkType('Module:Array.sum', 1, arr, 'table') | | return p.reduce(enum, function(x, y) return x + y end) |
| local res = 0 | |
| for i = 1, len(arr) do | |
| res = res + arr[i]
| |
| end
| |
| return res | |
| end | | end |
|
| |
|
| ---Extract a subtable from `arr`.
| | function p.take(enum, count, clone) |
| ---@generic T: any[]
| | libraryUtil.checkType('Module:Enum.take', 1, enum, 'table') |
| ---@param arr T
| | libraryUtil.checkType('Module:Enum.take', 2, count, 'number') |
| ---@param count integer # Length of the subtable.
| | libraryUtil.checkType('Module:Enum.take', 3, clone, 'boolean', true) |
| ---@param start? integer # Start index. Default is 1.
| | if clone then enum = mw.clone(enum) end |
| ---@return T
| | local x, _ = p.split(enum, count) |
| function Array.take(arr, count, start) | | return x |
| checkType('Module:Array.take', 1, arr, 'table') | |
| checkType('Module:Array.take', 2, count, 'number') | |
| checkType('Module:Array.take', 3, start, 'number', true) | |
| local x = {} | |
| start = start or 1 | |
| for i = start, math.min(len(arr), count + start - 1) do
| |
| table.insert(x, arr[i])
| |
| end
| |
| return setmetatable(x, getmetatable(arr)) | |
| end | | end |
|
| |
|
| ---Extract a subtable from `arr`.
| | function p.take_every(enum, n, clone) |
| ---```
| | libraryUtil.checkType('Module:Enum.take_every', 1, enum, 'table') |
| ---local t = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
| | libraryUtil.checkType('Module:Enum.take_every', 2, n, 'number') |
| ---local x = arr.take_every( t, 2 ) --> x = { 1, 3, 5, 7, 9 }
| | libraryUtil.checkType('Module:Enum.take_every', 3, clone, 'boolean', true) |
| ---local x = arr.take_every( t, 2, 3 ) --> x = { 3, 5, 7, 9 }
| | if clone then enum = mw.clone(enum) end |
| ---local x = arr.take_every( t, 2, 3, 2 ) --> x = { 3, 5 }
| |
| --- ```
| |
| ---@generic T: any[]
| |
| ---@param arr T
| |
| ---@param n integer # Step size.
| |
| ---@param start? integer # Start index.
| |
| ---@param count? integer # Max amount of elements to get.
| |
| ---@return T
| |
| function Array.take_every(arr, n, start, count) | |
| checkType('Module:Array.take_every', 1, arr, 'table') | |
| checkType('Module:Array.take_every', 2, n, 'number') | |
| checkType('Module:Array.take_every', 3, start, 'number', true) | |
| checkType('Module:Array.take_every', 4, count, 'number', true) | |
| count = count or len(arr)
| |
| start = start or 1
| |
| local stop = math.min(len(arr), start + n * (count - 1))
| |
| local r = {} | | local r = {} |
| local l = 0
| | for index, item in ipairs(enum) do |
| for i = start, stop, n do | | if (index - 1) % n == 0 then |
| l = l + 1 | | table.insert(r, item) |
| r[l] = arr[i] | | end |
| end | | end |
| return setmetatable(r, getmetatable(arr)) | | return r |
| end | | end |
|
| |
|
| ---Return a new table with all duplicates removed.
| | function p.unique(enum, fn, clone) |
| ---@generic T: any[]
| | libraryUtil.checkType('Module:Enum.unique', 1, enum, 'table') |
| ---@param arr T
| | libraryUtil.checkType('Module:Enum.unique', 2, fn, 'function', true) |
| ---@param fn? fun(elem: any): any # Function to generate an id for each element. The result will then contain elements that generated unique ids.
| | libraryUtil.checkType('Module:Enum.unique', 3, clone, 'boolean', true) |
| ---@return T
| | if clone then enum = mw.clone(enum) end |
| function Array.unique(arr, fn) | |
| checkType('Module:Array.unique', 1, arr, 'table') | |
| checkType('Module:Array.unique', 2, fn, 'function', true) | |
| fn = fn or function(item) return item end | | fn = fn or function(item) return item end |
| local r = {} | | local r = {} |
| local l = 0
| |
| local hash = {} | | local hash = {} |
| for i = 1, len(arr) do | | for _, item in ipairs(enum) do |
| local id = fn(arr[i]) | | local id = fn(item) |
| if not hash[id] then | | if not hash[id] then |
| l = l + 1 | | table.insert(r, item) |
| r[l] = arr[i]
| |
| hash[id] = true | | hash[id] = true |
| end | | end |
| end | | end |
| return setmetatable(r, getmetatable(arr)) | | return r |
| end | | end |
|
| |
|
| ---Combine elements with the same index from multiple arrays.
| | function p.zip(enums, clone) |
| ---```
| | libraryUtil.checkType('Module:Enum.zip', 1, enums, 'table') |
| ---local x = {1, 2, 3}
| | libraryUtil.checkType('Module:Enum.zip', 2, clone, 'boolean', true) |
| ---local y = {4, 5, 6, 7}
| | if clone then enums = mw.clone(enums) end |
| ---local z = arr.zip( x, y ) --> z = { { 1, 4 }, { 2, 5 }, { 3, 6 }, { 7 } }
| |
| ---```
| |
| ---@param ... any[]
| |
| ---@return Array
| |
| function Array.zip(...)
| |
| local arrs = { ... } | |
| checkType('Module:Array.zip', 1, arrs[1], 'table')
| |
| local r = {} | | local r = {} |
| local _, longest = Array.max_by(arrs, function(arr) return len(arr) end) | | local _, longest = p.max_by(enums, function(enum) return #enum end) |
| for i = 1, longest do | | for i = 1, longest do |
| local q = {} | | local q = {} |
| for j = 1, len(arrs) do | | for j = 1, #enums do |
| table.insert(q, arrs[j][i]) | | table.insert(q, enums[j][i]) |
| end
| |
| table.insert(r, setmetatable(q, Array))
| |
| end
| |
| return setmetatable(r, Array)
| |
| end
| |
| | |
| -- Range indexing has a performance impact so this is placed in a separate subclass
| |
| Array.RI_mt = {}
| |
| for k, v in pairs(Array) do
| |
| Array.RI_mt[k] = v
| |
| end
| |
| | |
| function Array.RI_mt.__index(t, k)
| |
| if type(k) == 'table' then
| |
| local res = {}
| |
| for i = 1, len(k) do
| |
| res[i] = t[k[i]]
| |
| end | | end |
| return setmetatable(res, Array) | | table.insert(r, q) |
| else
| |
| return Array[k]
| |
| end | | end |
| | return r |
| end | | end |
|
| |
|
| function Array.RI_mt.__newindex(t, k, v) | | function p.take_from(enum, index, count) |
| if type(k) == 'table' then | | libraryUtil.checkType('Module:Enum.take_from', 1, enum, 'table') |
| if type(v) == 'table' then
| | libraryUtil.checkType('Module:Enum.take_from', 2, index, 'number') |
| for i = 1, len(k) do
| | libraryUtil.checkType('Module:Enum.take_from', 3, count, 'number') |
| t[k[i]] = v[i]
| | local x, _ = p.split(p.reject(enum, |
| end
| | function(item, idx) |
| else | | return idx < index |
| for i = 1, len(k) do
| |
| t[k[i]] = v
| |
| end | |
| end | | end |
| else | | ), count) |
| rawset(t, k, v)
| | return x |
| end | |
| end | | end |
|
| |
|
| ---Enable range indexing on the input array.
| | function p.intersect(enum1, enum2, clone) |
| ---
| | libraryUtil.checkType('Module:Enum.intersect', 1, enum1, 'table') |
| ---This has a performance impact on reads and writes to the table.
| | libraryUtil.checkType('Module:Enum.intersect', 2, enum2, 'table') |
| ---```
| | libraryUtil.checkType('Module:Enum.intersect', 3, clone, 'boolean', true) |
| ---local t = arr{10, 11, 12, 13, 14, 15}:ri()
| | if clone then enum1 = mw.clone(enum1); enum2 = mw.clone(enum2) end |
| ---print( t[{2, 3}] ) --> { 11, 12 }
| | return p.any(enum1, function(item1) return p.any(enum2, function(item2) return item1==item2 end) end) |
| ---```
| |
| ---@param arr any[]
| |
| ---@param recursive? boolean # Default is false.
| |
| ---@return Array
| |
| function Array.ri(arr, recursive)
| |
| checkType('Module:Array.ri', 1, arr, 'table') | |
| checkType('Module:Array.ri', 2, recursive, 'boolean', true) | |
| arr = arr or {}
| |
| if recursive then | |
| for _, v in pairs(arr) do
| |
| if type(v) == 'table' then
| |
| Array.ri(v, true)
| |
| end
| |
| end
| |
| end | |
| | |
| if getmetatable(arr) == nil or getmetatable(arr) == Array then
| |
| setmetatable(arr, Array.RI_mt)
| |
| end
| |
| | |
| return arr
| |
| end | | end |
|
| |
|
| ---Globally enable range indexing on all Array objects by default.
| | function p.contains(enum, elem, clone) |
| ---@param set boolean
| | libraryUtil.checkType('Module:Enum.contains', 1, enum, 'table') |
| function Array.allwaysAllowRangeIndexing(set)
| | libraryUtil.checkType('Module:Enum.contains', 3, clone, 'boolean', true) |
| checkType('Module:Array.allwaysAllowRangeIndexing', 1, set, 'boolean') | | if clone then enum = mw.clone(enum); elem = mw.clone(elem) end |
| if set then | | return p.any(enum, function(item) return item == elem end) |
| Array.__index = Array.RI_mt.__index
| |
| Array.__newindex = Array.RI_mt.__newindex
| |
| else | |
| Array.__index = Array
| |
| Array.__newindex = nil
| |
| end
| |
| end | | end |
|
| |
|
| return Array | | return p |
| | -- </nowiki> |