Editing Module:ArrayGive feedback
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
| Latest revision | Your text | ||
| Line 2: | Line 2: | ||
local checkType = libraryUtil.checkType | local checkType = libraryUtil.checkType | ||
local checkTypeMulti = libraryUtil.checkTypeMulti | local checkTypeMulti = libraryUtil.checkTypeMulti | ||
---@class Array | ---@class Array | ||
| Line 45: | Line 14: | ||
---@operator pow(number|number[]|Array): Array | ---@operator pow(number|number[]|Array): Array | ||
local Array = { | local Array = { | ||
pop = table.remove | pop = table.remove | ||
} | } | ||
Array.__index = Array | Array.__index = Array | ||
| Line 56: | Line 24: | ||
end | end | ||
}) | }) | ||
-- function Array.__tostring(arr) | |||
-- -- local dumpObject = require('Module:Logger').dumpObject | |||
-- require 'log' | |||
-- local dumpObject = dumpObject | |||
-- local mt = getmetatable(arr) | |||
-- setmetatable(arr, nil) | |||
-- local str = dumpObject(arr, {clean=true, collapseLimit=100}) | |||
-- setmetatable(arr, mt) | |||
-- return str | |||
-- end | |||
function Array.__concat(lhs, rhs) | function Array.__concat(lhs, rhs) | ||
if type(lhs) == 'table' and type(rhs) == 'table' then | if type(lhs) == 'table' and type(rhs) == 'table' then | ||
local res = {} | local res = {} | ||
for i = 1, #lhs do | |||
for i = 1, | |||
res[i] = lhs[i] | res[i] = lhs[i] | ||
end | end | ||
for i = 1, | local l = #lhs | ||
res[ | for i = 1, #rhs do | ||
res[i + l] = rhs[i] | |||
end | end | ||
return setmetatable(res, getmetatable(lhs) or getmetatable(rhs)) | return setmetatable(res, getmetatable(lhs) or getmetatable(rhs)) | ||
| Line 80: | Line 59: | ||
---@param rhs number|number[]|Array | ---@param rhs number|number[]|Array | ||
---@param funName string | ---@param funName string | ||
---@param fun fun(lhs: number, rhs: number): number | ---@param fun fun(lhs: number, rhs: number): number | ||
---@return Array | ---@return Array | ||
local function mathTemplate(lhs, rhs, funName | local function mathTemplate(lhs, rhs, funName, fun) | ||
checkTypeMulti('Module:Array.' .. funName, 1, lhs, {'number', 'table'}) | checkTypeMulti('Module:Array.' .. funName, 1, lhs, {'number', 'table'}) | ||
checkTypeMulti('Module:Array.' .. funName, 2, rhs, {'number', 'table'}) | checkTypeMulti('Module:Array.' .. funName, 2, rhs, {'number', 'table'}) | ||
| Line 89: | Line 67: | ||
if type(lhs) == 'number' then | if type(lhs) == 'number' then | ||
for i = 1, | for i = 1, #rhs do | ||
res[i] = fun(lhs, rhs[i]) | res[i] = fun(lhs, rhs[i]) | ||
end | end | ||
elseif type(rhs) == 'number' then | elseif type(rhs) == 'number' then | ||
for i = 1, | for i = 1, #lhs do | ||
res[i] = fun(lhs[i], rhs) | res[i] = fun(lhs[i], rhs) | ||
end | end | ||
else | else | ||
assert( | assert(#lhs == #rhs, string.format('Tables are not equal length (lhs=%d, rhs=%d)', #lhs, #rhs)) | ||
for i = 1, | for i = 1, #lhs do | ||
res[i] = fun(lhs[i], rhs[i]) | res[i] = fun(lhs[i], rhs[i]) | ||
end | end | ||
| Line 107: | Line 85: | ||
function Array.__add(lhs, rhs) | function Array.__add(lhs, rhs) | ||
return mathTemplate(lhs, rhs, '__add | return mathTemplate(lhs, rhs, '__add', function(x, y) return x + y end) | ||
end | end | ||
function Array.__sub(lhs, rhs) | function Array.__sub(lhs, rhs) | ||
return mathTemplate(lhs, rhs, '__sub | return mathTemplate(lhs, rhs, '__sub', function(x, y) return x - y end) | ||
end | end | ||
function Array.__mul(lhs, rhs) | function Array.__mul(lhs, rhs) | ||
return mathTemplate(lhs, rhs, '__mul | return mathTemplate(lhs, rhs, '__mul', function(x, y) return x * y end) | ||
end | end | ||
function Array.__div(lhs, rhs) | function Array.__div(lhs, rhs) | ||
return mathTemplate(lhs, rhs, '__div | return mathTemplate(lhs, rhs, '__div', function(x, y) return x / y end) | ||
end | end | ||
function Array.__pow(lhs, rhs) | function Array.__pow(lhs, rhs) | ||
return mathTemplate(lhs, rhs, '__pow | return mathTemplate(lhs, rhs, '__pow', function(x, y) return x ^ y end) | ||
end | end | ||
function Array.__eq(lhs, rhs) | function Array.__eq(lhs, rhs) | ||
if | if #lhs ~= #rhs then | ||
return false | return false | ||
end | end | ||
for i = 1, | for i = 1, #lhs do | ||
if lhs[i] ~= rhs[i] then | if lhs[i] ~= rhs[i] then | ||
return false | return false | ||
| Line 152: | Line 130: | ||
fn = function(item) return item == val end | fn = function(item) return item == val end | ||
end | end | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
---@diagnostic disable-next-line: redundant-parameter | ---@diagnostic disable-next-line: redundant-parameter | ||
if not fn(arr[i], i) then | if not fn(arr[i], i) then | ||
return false | return false | ||
end | end | ||
i = i + 1 | |||
end | end | ||
return true | return true | ||
| Line 175: | Line 155: | ||
fn = function(item) return item == val end | fn = function(item) return item == val end | ||
end | end | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
---@diagnostic disable-next-line: redundant-parameter | ---@diagnostic disable-next-line: redundant-parameter | ||
if fn(arr[i], i) then | if fn(arr[i], i) then | ||
return true | return true | ||
end | end | ||
i = i + 1 | |||
end | end | ||
return false | return false | ||
| Line 189: | Line 171: | ||
function Array.clean(arr) | function Array.clean(arr) | ||
checkType('Module:Array.clean', 1, arr, 'table') | checkType('Module:Array.clean', 1, arr, 'table') | ||
for i = 1, | for i = 1, #arr do | ||
if type(arr[i]) == 'table' then | if type(arr[i]) == 'table' then | ||
Array.clean(arr[i]) | Array.clean(arr[i]) | ||
| Line 207: | Line 189: | ||
checkType('Module:Array.clone', 2, deep, 'boolean', true) | checkType('Module:Array.clone', 2, deep, 'boolean', true) | ||
local res = {} | local res = {} | ||
for i = 1, | for i = 1, #arr do | ||
if deep == true and type(arr[i]) == 'table' then | if deep == true and type(arr[i]) == 'table' then | ||
res[i] = Array.clone(arr[i], true) | res[i] = Array.clone(arr[i], true) | ||
| Line 223: | Line 205: | ||
function Array.contains(arr, val) | function Array.contains(arr, val) | ||
checkType('Module:Array.contains', 1, arr, 'table') | checkType('Module:Array.contains', 1, arr, 'table') | ||
for i = 1, | for i = 1, #arr do | ||
if arr[i] == val then | if arr[i] == val then | ||
return true | return true | ||
| Line 239: | Line 221: | ||
checkType('Module:Array.containsAny', 2, t, 'table') | checkType('Module:Array.containsAny', 2, t, 'table') | ||
local lookupTbl = {} | local lookupTbl = {} | ||
for i = 1, | for i = 1, #t do | ||
lookupTbl[t[i]] = true | lookupTbl[t[i]] = true | ||
end | end | ||
for i = 1, | for i = 1, #arr do | ||
if lookupTbl[arr[i]] then | if lookupTbl[arr[i]] then | ||
return true | return true | ||
| Line 258: | Line 240: | ||
checkType('Module:Array.containsAll', 2, t, 'table') | checkType('Module:Array.containsAll', 2, t, 'table') | ||
local lookupTbl = {} | local lookupTbl = {} | ||
local l = #t | |||
local trueCount = 0 | local trueCount = 0 | ||
for i = 1, l do | for i = 1, l do | ||
lookupTbl[t[i]] = false | lookupTbl[t[i]] = false | ||
end | end | ||
for i = 1, | for i = 1, #arr do | ||
if lookupTbl[arr[i]] == false then | if lookupTbl[arr[i]] == false then | ||
lookupTbl[arr[i]] = true | lookupTbl[arr[i]] = true | ||
| Line 284: | Line 266: | ||
checkType('Module:Array.convolve', 2, y, 'table') | checkType('Module:Array.convolve', 2, y, 'table') | ||
local z = {} | local z = {} | ||
local xLen, yLen = | local xLen, yLen = #x, #y | ||
for j = 1, (xLen + yLen - 1) do | for j = 1, (xLen + yLen - 1) do | ||
local sum = 0 | local sum = 0 | ||
| Line 330: | Line 312: | ||
end | end | ||
local count = 0 | local count = 0 | ||
for i = 1, | for i = 1, #arr do | ||
if val(arr[i]) then | if val(arr[i]) then | ||
count = count + 1 | count = count + 1 | ||
| Line 347: | Line 329: | ||
checkType('Module:Array.diff', 2, order, 'number', true) | checkType('Module:Array.diff', 2, order, 'number', true) | ||
local res = {} | local res = {} | ||
for i = 1, | for i = 1, #arr - 1 do | ||
res[i] = arr[i+1] - arr[i] | res[i] = arr[i+1] - arr[i] | ||
end | end | ||
| Line 362: | Line 344: | ||
checkType('Module:Array.each', 1, arr, 'table') | checkType('Module:Array.each', 1, arr, 'table') | ||
checkType('Module:Array.each', 2, fn, 'function') | checkType('Module:Array.each', 2, fn, 'function') | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
fn(arr[i], i) | fn(arr[i], i) | ||
i = i + 1 | |||
end | end | ||
end | end | ||
| Line 376: | Line 360: | ||
checkType('Module:Array.filter', 2, fn, 'function') | checkType('Module:Array.filter', 2, fn, 'function') | ||
local r = {} | local r = {} | ||
local | local len = 0 | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
if fn(arr[i], i) then | if fn(arr[i], i) then | ||
len = len + 1 | |||
r[ | r[len] = arr[i] | ||
end | end | ||
i = i + 1 | |||
end | end | ||
return setmetatable(r, getmetatable(arr)) | return setmetatable(r, getmetatable(arr)) | ||
| Line 399: | Line 385: | ||
fn = function(item) return item == _val end | fn = function(item) return item == _val end | ||
end | end | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
---@diagnostic disable-next-line: redundant-parameter | ---@diagnostic disable-next-line: redundant-parameter | ||
if fn(arr[i], i) then | if fn(arr[i], i) then | ||
return arr[i], i | return arr[i], i | ||
end | end | ||
i = i + 1 | |||
end | end | ||
return default, nil | return default, nil | ||
| Line 420: | Line 408: | ||
val = function(item) return item == _val end | val = function(item) return item == _val end | ||
end | end | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
---@diagnostic disable-next-line: redundant-parameter | ---@diagnostic disable-next-line: redundant-parameter | ||
if val(arr[i], i) then | if val(arr[i], i) then | ||
return i | return i | ||
end | end | ||
i = i + 1 | |||
end | end | ||
return default | return default | ||
| Line 441: | Line 431: | ||
end | end | ||
local res = {} | local res = {} | ||
for i = 1, | for i = 1, #indexes do | ||
res[i] = arr[indexes[i]] | res[i] = arr[indexes[i]] | ||
end | end | ||
| Line 459: | Line 449: | ||
local res = {} | local res = {} | ||
start = start or 1 | start = start or 1 | ||
stop = stop or | stop = stop or #arr | ||
res[1] = arr[start] | res[1] = arr[start] | ||
for i = 1, stop - start do | for i = 1, stop - start do | ||
| Line 477: | Line 467: | ||
local arr2Elements = {} | local arr2Elements = {} | ||
local res = {} | local res = {} | ||
local | local len = 0 | ||
Array.each(arr2, function(item) arr2Elements[item] = true end) | Array.each(arr2, function(item) arr2Elements[item] = true end) | ||
Array.each(arr1, function(item) | Array.each(arr1, function(item) | ||
if arr2Elements[item] then | if arr2Elements[item] then | ||
len = len + 1 | |||
res[ | res[len] = item | ||
end | end | ||
end) | end) | ||
| Line 497: | Line 487: | ||
local small = {} | local small = {} | ||
local large | local large | ||
if | if #arr1 <= #arr2 then | ||
Array.each(arr1, function(item) small[item] = true end) | Array.each(arr1, function(item) small[item] = true end) | ||
large = arr2 | large = arr2 | ||
| Line 522: | Line 512: | ||
unpackVal, index = index, nil | unpackVal, index = index, nil | ||
end | end | ||
local | local len = #arr | ||
index = index or ( | index = index or (len + 1) | ||
local mt = getmetatable(arr) | local mt = getmetatable(arr) | ||
setmetatable(arr, nil) | setmetatable(arr, nil) | ||
if | if type(val) == 'table' and unpackVal then | ||
local | local len2 = #val | ||
for i = 0, | for i = 0, len - index do | ||
arr[ | arr[len + len2 - i] = arr[len - i] | ||
end | end | ||
for i = 0, | for i = 0, len2 - 1 do | ||
arr[index + i] = val[i + 1] | arr[index + i] = val[i + 1] | ||
end | end | ||
| Line 549: | Line 539: | ||
checkType('Module:Array.last', 1, arr, 'table') | checkType('Module:Array.last', 1, arr, 'table') | ||
checkType('Module:Array.last', 2, offset, 'number', true) | checkType('Module:Array.last', 2, offset, 'number', true) | ||
return arr[ | return arr[#arr + offset] | ||
end | end | ||
| Line 560: | Line 550: | ||
checkType('Module:Array.map', 1, arr, 'table') | checkType('Module:Array.map', 1, arr, 'table') | ||
checkType('Module:Array.map', 2, fn, 'function') | checkType('Module:Array.map', 2, fn, 'function') | ||
local | local len = 0 | ||
local r = {} | local r = {} | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
local tmp = fn(arr[i], i) | local tmp = fn(arr[i], i) | ||
if tmp ~= nil then | if tmp ~= nil then | ||
len = len + 1 | |||
r[ | r[len] = tmp | ||
end | end | ||
i = i + 1 | |||
end | end | ||
return setmetatable(r, getmetatable(arr)) | return setmetatable(r, getmetatable(arr)) | ||
| Line 673: | Line 665: | ||
return setmetatable(obj, { | return setmetatable(obj, { | ||
__call = function() n = n + step return n end, | __call = function() n = n + step return n end, | ||
__tostring = function() return | __tostring = function() return n end, | ||
__index = function() return n end, | __index = function() return n end, | ||
__newindex = function(self, k, v) | __newindex = function(self, k, v) | ||
| Line 726: | Line 718: | ||
checkType('Module:Array.reduce', 2, fn, 'function') | checkType('Module:Array.reduce', 2, fn, 'function') | ||
local acc = accumulator | local acc = accumulator | ||
local | local i = 1 | ||
if acc == nil then | if acc == nil then | ||
acc = arr[1] | acc = arr[1] | ||
i = 2 | |||
end | end | ||
while arr[i] ~= nil do | |||
acc = fn(arr[i], acc, i) | acc = fn(arr[i], acc, i) | ||
i = i + 1 | |||
end | end | ||
return acc | return acc | ||
| Line 754: | Line 747: | ||
end | end | ||
local r = {} | local r = {} | ||
local | local len = 0 | ||
if type(val) == 'function' then | if type(val) == 'function' then | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
if not val(arr[i], i) then | if not val(arr[i], i) then | ||
len = len + 1 | |||
r[ | r[len] = arr[i] | ||
end | end | ||
i = i + 1 | |||
end | end | ||
else | else | ||
local rejectMap = {} | local rejectMap = {} | ||
Array.each(val --[[@as any[] ]], function(item) rejectMap[item] = true end) | Array.each(val --[[@as any[] ]], function(item) rejectMap[item] = true end) | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
if not rejectMap[arr[i]] then | if not rejectMap[arr[i]] then | ||
len = len + 1 | |||
r[ | r[len] = arr[i] | ||
end | end | ||
i = i + 1 | |||
end | end | ||
end | end | ||
| Line 807: | Line 804: | ||
local acc = accumulator | local acc = accumulator | ||
local r = {} | local r = {} | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
if i == 1 and not accumulator then | if i == 1 and not accumulator then | ||
acc = arr[i] | acc = arr[i] | ||
| Line 814: | Line 812: | ||
end | end | ||
r[i] = acc | r[i] = acc | ||
i = i + 1 | |||
end | end | ||
return setmetatable(r, getmetatable(arr)) | return setmetatable(r, getmetatable(arr)) | ||
| Line 837: | Line 836: | ||
end | end | ||
if type(values) == 'table' then | if type(values) == 'table' then | ||
assert( | assert(#indexes == #values, string.format("Module:Array.set: 'indexes' and 'values' arrays are not equal length (#indexes = %d, #values = %d)", #indexes, #values)) | ||
for i = 1, | for i = 1, #indexes do | ||
arr[indexes[i]] = values[i] | arr[indexes[i]] = values[i] | ||
end | end | ||
else | else | ||
for i = 1, | for i = 1, #indexes do | ||
arr[indexes[i]] = values | arr[indexes[i]] = values | ||
end | end | ||
| Line 860: | Line 859: | ||
checkType('Module:Array.slice', 2, start, 'number', true) | checkType('Module:Array.slice', 2, start, 'number', true) | ||
checkType('Module:Array.slice', 3, stop, 'number', true) | checkType('Module:Array.slice', 3, stop, 'number', true) | ||
start = start or | start = start or #arr | ||
if start < 0 then | if start < 0 then | ||
start = | start = #arr + start | ||
end | end | ||
if stop == nil then | if stop == nil then | ||
| Line 869: | Line 868: | ||
end | end | ||
if stop < 0 then | if stop < 0 then | ||
stop = | stop = #arr + stop | ||
end | end | ||
local r = {} | local r = {} | ||
| Line 891: | Line 890: | ||
local x = {} | local x = {} | ||
local y = {} | local y = {} | ||
for i = 1, | for i = 1, #arr do | ||
table.insert(i <= index and x or y, arr[i]) | table.insert(i <= index and x or y, arr[i]) | ||
end | end | ||
| Line 903: | Line 902: | ||
checkType('Module:Array.sum', 1, arr, 'table') | checkType('Module:Array.sum', 1, arr, 'table') | ||
local res = 0 | local res = 0 | ||
for i = 1, | for i = 1, #arr do | ||
res = res + arr[i] | res = res + arr[i] | ||
end | end | ||
| Line 921: | Line 920: | ||
local x = {} | local x = {} | ||
start = start or 1 | start = start or 1 | ||
for i = start, math.min( | for i = start, math.min(#arr, count + start - 1) do | ||
table.insert(x, arr[i]) | table.insert(x, arr[i]) | ||
end | end | ||
| Line 931: | Line 930: | ||
---local t = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } | ---local t = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } | ||
---local x = arr.take_every( t, 2 ) --> x = { 1, 3, 5, 7, 9 } | ---local x = arr.take_every( t, 2 ) --> x = { 1, 3, 5, 7, 9 } | ||
---local x = arr.take_every( t, 2, 3 ) --> x = { 3, 5 | ---local x = arr.take_every( t, 2, 3 ) --> x = { 1, 3, 5 } | ||
---local x = arr.take_every( t, 2, 3, 2 ) --> x = { | ---local x = arr.take_every( t, 2, 3, 2 ) --> x = { 2, 4, 6 } | ||
--- ``` | --- ``` | ||
---@generic T: any[] | ---@generic T: any[] | ||
---@param arr T | ---@param arr T | ||
---@param n integer # Step size. | ---@param n integer # Step size. | ||
---@param count? integer # Max amount of elements to get. | |||
---@param start? integer # Start index. | ---@param start? integer # Start index. | ||
---@return T | ---@return T | ||
function Array.take_every(arr, n, start | function Array.take_every(arr, n, count, start) | ||
checkType('Module:Array.take_every', 1, arr, 'table') | checkType('Module:Array.take_every', 1, arr, 'table') | ||
checkType('Module:Array.take_every', 2, n, 'number') | checkType('Module:Array.take_every', 2, n, 'number') | ||
checkType('Module:Array.take_every', 3, | checkType('Module:Array.take_every', 3, count, 'number', true) | ||
checkType('Module:Array.take_every', 4, | checkType('Module:Array.take_every', 4, start, 'number', true) | ||
count = count or | count = count or #arr | ||
local r = {} | local r = {} | ||
local | local len = 0 | ||
local i = start or 1 | |||
while arr[i] ~= nil and len < count do | |||
r[ | len = len + 1 | ||
r[len] = arr[i] | |||
i = i + n | |||
end | end | ||
return setmetatable(r, getmetatable(arr)) | return setmetatable(r, getmetatable(arr)) | ||
| Line 967: | Line 966: | ||
fn = fn or function(item) return item end | fn = fn or function(item) return item end | ||
local r = {} | local r = {} | ||
local | local len = 0 | ||
local hash = {} | local hash = {} | ||
local i = 1 | |||
while arr[i] ~= nil do | |||
local id = fn(arr[i]) | local id = fn(arr[i]) | ||
if not hash[id] then | if not hash[id] then | ||
len = len + 1 | |||
r[ | r[len] = arr[i] | ||
hash[id] = true | hash[id] = true | ||
end | end | ||
i = i + 1 | |||
end | end | ||
return setmetatable(r, getmetatable(arr)) | return setmetatable(r, getmetatable(arr)) | ||
| Line 992: | Line 993: | ||
checkType('Module:Array.zip', 1, arrs[1], 'table') | checkType('Module:Array.zip', 1, arrs[1], 'table') | ||
local r = {} | local r = {} | ||
local _, longest = Array.max_by(arrs, function(arr) return | local _, longest = Array.max_by(arrs, function(arr) return #arr end) | ||
for i = 1, longest do | for i = 1, longest do | ||
local q = {} | local q = {} | ||
for j = 1, | for j = 1, #arrs do | ||
table.insert(q, arrs[j][i]) | table.insert(q, arrs[j][i]) | ||
end | end | ||
| Line 1,012: | Line 1,013: | ||
if type(k) == 'table' then | if type(k) == 'table' then | ||
local res = {} | local res = {} | ||
for i = 1, | for i = 1, #k do | ||
res[i] = t[k[i]] | res[i] = t[k[i]] | ||
end | end | ||
| Line 1,024: | Line 1,025: | ||
if type(k) == 'table' then | if type(k) == 'table' then | ||
if type(v) == 'table' then | if type(v) == 'table' then | ||
for i = 1, | for i = 1, #k do | ||
t[k[i]] = v[i] | t[k[i]] = v[i] | ||
end | end | ||
else | else | ||
for i = 1, | for i = 1, #k do | ||
t[k[i]] = v | t[k[i]] = v | ||
end | end | ||