Editing Module:Array

Warning: You are not logged in. Once you make an edit, a temporary account will be created for you. Learn more. Log in or create an account to continue receiving notifications after this account expires, and to access other features.
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
---Returns the length of the array but it also works on proxy arrays
---@param arr any[]
---@return integer
local function len(arr)
local l = #arr
if l == 0 then
if arr[1] ~= nil then
-- Exponential search to find length of proxy table
local low = 1
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
else
return l
end
end


---@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
len = len
}
}
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 = {}
local l1 = len(lhs)
for i = 1, #lhs do
for i = 1, l1 do
res[i] = lhs[i]
res[i] = lhs[i]
end
end
for i = 1, len(rhs) do
local l = #lhs
res[l1 + i] = rhs[i]
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 89: Line 68:


if type(lhs) == 'number' then
if type(lhs) == 'number' then
for i = 1, len(rhs) do
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, len(lhs) do
for i = 1, #lhs do
res[i] = fun(lhs[i], rhs)
res[i] = fun(lhs[i], rhs)
end
end
else
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)))
assert(#lhs == #rhs, string.format('Elementwise %s failed because arrays have different sizes (left: %d, right: %d)', opName, #lhs, #rhs))
for i = 1, len(lhs) do
for i = 1, #lhs do
res[i] = fun(lhs[i], rhs[i])
res[i] = fun(lhs[i], rhs[i])
end
end
Line 127: Line 106:


function Array.__eq(lhs, rhs)
function Array.__eq(lhs, rhs)
if len(lhs) ~= len(rhs) then
if #lhs ~= #rhs then
return false
return false
end
end
for i = 1, len(lhs) do
for i = 1, #lhs do
if lhs[i] ~= rhs[i] then
if lhs[i] ~= rhs[i] then
return false
return false
Line 152: Line 131:
fn = function(item) return item == val end
fn = function(item) return item == val end
end
end
for i = 1, len(arr) do
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 156:
fn = function(item) return item == val end
fn = function(item) return item == val end
end
end
for i = 1, len(arr) do
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 172:
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, len(arr) do
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 190:
checkType('Module:Array.clone', 2, deep, 'boolean', true)
checkType('Module:Array.clone', 2, deep, 'boolean', true)
local res = {}
local res = {}
for i = 1, len(arr) do
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 206:
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, len(arr) do
for i = 1, #arr do
if arr[i] == val then
if arr[i] == val then
return true
return true
Line 239: Line 222:
checkType('Module:Array.containsAny', 2, t, 'table')
checkType('Module:Array.containsAny', 2, t, 'table')
local lookupTbl = {}
local lookupTbl = {}
for i = 1, len(t) do
for i = 1, #t do
lookupTbl[t[i]] = true
lookupTbl[t[i]] = true
end
end
for i = 1, len(arr) do
for i = 1, #arr do
if lookupTbl[arr[i]] then
if lookupTbl[arr[i]] then
return true
return true
Line 258: Line 241:
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
local l = len(t)
for i = 1, l do
for i = 1, l do
lookupTbl[t[i]] = false
lookupTbl[t[i]] = false
end
end
for i = 1, len(arr) do
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 267:
checkType('Module:Array.convolve', 2, y, 'table')
checkType('Module:Array.convolve', 2, y, 'table')
local z = {}
local z = {}
     local xLen, yLen = len(x), len(y)
     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 313:
end
end
local count = 0
local count = 0
for i = 1, len(arr) do
for i = 1, #arr do
if val(arr[i]) then
if val(arr[i]) then
count = count + 1
count = count + 1
Line 347: Line 330:
checkType('Module:Array.diff', 2, order, 'number', true)
checkType('Module:Array.diff', 2, order, 'number', true)
local res = {}
local res = {}
for i = 1, len(arr) - 1 do
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 345:
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')
for i = 1, len(arr) do
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 361:
checkType('Module:Array.filter', 2, fn, 'function')
checkType('Module:Array.filter', 2, fn, 'function')
local r = {}
local r = {}
local l = 0
local len = 0
for i = 1, len(arr) do
local i = 1
while arr[i] ~= nil do
if fn(arr[i], i) then
if fn(arr[i], i) then
l = l + 1
len = len + 1
r[l] = arr[i]
r[len] = arr[i]
end
end
i = i + 1
end
end
return setmetatable(r, getmetatable(arr))
return setmetatable(r, getmetatable(arr))
Line 399: Line 386:
fn = function(item) return item == _val end
fn = function(item) return item == _val end
end
end
for i = 1, len(arr) do
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 409:
val = function(item) return item == _val end
val = function(item) return item == _val end
end
end
for i = 1, len(arr) do
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 432:
end
end
local res = {}
local res = {}
for i = 1, len(indexes) do
for i = 1, #indexes do
res[i] = arr[indexes[i]]
res[i] = arr[indexes[i]]
end
end
Line 459: Line 450:
local res = {}
local res = {}
start = start or 1
start = start or 1
stop = stop or len(arr)
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 468:
local arr2Elements = {}
local arr2Elements = {}
local res = {}
local res = {}
local l = 0
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
l = l + 1
len = len + 1
res[l] = item
res[len] = item
end
end
end)
end)
Line 497: Line 488:
local small = {}
local small = {}
local large
local large
if len(arr1) <= len(arr2) then
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 513:
unpackVal, index = index, nil
unpackVal, index = index, nil
end
end
local l = len(arr)
local len = #arr
index = index or (l + 1)
index = index or (len + 1)
local mt = getmetatable(arr)
local mt = getmetatable(arr)
setmetatable(arr, nil)
setmetatable(arr, nil)


if unpackVal and type(val) == 'table' then
if type(val) == 'table' and unpackVal then
local l2 = len(val)
local len2 = #val
for i = 0, l - index do
for i = 0, len - index do
arr[l + l2 - i] = arr[l - i]
arr[len + len2 - i] = arr[len - i]
end
end
for i = 0, l2 - 1 do
for i = 0, len2 - 1 do
arr[index + i] = val[i + 1]
arr[index + i] = val[i + 1]
end
end
Line 549: Line 540:
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[len(arr) + offset]
return arr[#arr + offset]
end
end


Line 560: Line 551:
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 l = 0
local len = 0
local r = {}
local r = {}
for i = 1, len(arr) do
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
l = l + 1
len = len + 1
r[l] = tmp
r[len] = tmp
end
end
i = i + 1
end
end
return setmetatable(r, getmetatable(arr))
return setmetatable(r, getmetatable(arr))
Line 673: Line 666:
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(n) end,
__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 719:
checkType('Module:Array.reduce', 2, fn, 'function')
checkType('Module:Array.reduce', 2, fn, 'function')
local acc = accumulator
local acc = accumulator
local start = 1
local i = 1
if acc == nil then
if acc == nil then
acc = arr[1]
acc = arr[1]
start = 2
i = 2
end
end
for i = start, len(arr) do
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 748:
end
end
local r = {}
local r = {}
local l = 0
local len = 0
if type(val) == 'function' then
if type(val) == 'function' then
for i = 1, len(arr) do
local i = 1
while arr[i] ~= nil do
if not val(arr[i], i) then
if not val(arr[i], i) then
l = l + 1
len = len + 1
r[l] = arr[i]
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)
for i = 1, len(arr) do
local i = 1
while arr[i] ~= nil do
if not rejectMap[arr[i]] then
if not rejectMap[arr[i]] then
l = l + 1
len = len + 1
r[l] = arr[i]
r[len] = arr[i]
end
end
i = i + 1
end
end
end
end
Line 807: Line 805:
local acc = accumulator
local acc = accumulator
local r = {}
local r = {}
for i = 1, len(arr) do
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 813:
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 837:
end
end
if type(values) == 'table' then
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)))
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, len(indexes) do
for i = 1, #indexes do
arr[indexes[i]] = values[i]
arr[indexes[i]] = values[i]
end
end
else
else
for i = 1, len(indexes) do
for i = 1, #indexes do
arr[indexes[i]] = values
arr[indexes[i]] = values
end
end
Line 860: Line 860:
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 len(arr)
start = start or #arr
if start < 0 then
if start < 0 then
start = len(arr) + start
start = #arr + start
end
end
if stop == nil then
if stop == nil then
Line 869: Line 869:
end
end
if stop < 0 then
if stop < 0 then
stop = len(arr) + stop
stop = #arr + stop
end
end
local r = {}
local r = {}
Line 891: Line 891:
local x = {}
local x = {}
local y = {}
local y = {}
for i = 1, len(arr) do
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 903:
checkType('Module:Array.sum', 1, arr, 'table')
checkType('Module:Array.sum', 1, arr, 'table')
local res = 0
local res = 0
for i = 1, len(arr) do
for i = 1, #arr do
res = res + arr[i]
res = res + arr[i]
end
end
Line 921: Line 921:
local x = {}
local x = {}
start = start or 1
start = start or 1
for i = start, math.min(len(arr), count + start - 1) do
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 931:
---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, 7, 9 }
---local x = arr.take_every( t, 2, 3 )    --> x = { 1, 3, 5 }
---local x = arr.take_every( t, 2, 3, 2 ) --> x = { 3, 5 }
---local x = arr.take_every( t, 2, 3, 2 ) --> x = { 2, 4, 6 }
--- ```
--- ```
---@generic T: any[]
---@generic T: any[]
Line 945: Line 945:
checkType('Module:Array.take_every', 3, start, 'number', true)
checkType('Module:Array.take_every', 3, start, 'number', true)
checkType('Module:Array.take_every', 4, count, 'number', true)
checkType('Module:Array.take_every', 4, count, 'number', true)
count = count or len(arr)
count = count or #arr
start = start or 1
local stop = math.min(len(arr), start + n * (count - 1))
local r = {}
local r = {}
local l = 0
local len = 0
for i = start, stop, n do
local i = start or 1
l = l + 1
while arr[i] ~= nil and len < count do
r[l] = arr[i]
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 967:
fn = fn or function(item) return item end
fn = fn or function(item) return item end
local r = {}
local r = {}
local l = 0
local len = 0
local hash = {}
local hash = {}
for i = 1, len(arr) do
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
l = l + 1
len = len + 1
r[l] = arr[i]
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 994:
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 len(arr) end)
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, len(arrs) do
for j = 1, #arrs do
table.insert(q, arrs[j][i])
table.insert(q, arrs[j][i])
end
end
Line 1,012: Line 1,014:
if type(k) == 'table' then
if type(k) == 'table' then
local res = {}
local res = {}
for i = 1, len(k) do
for i = 1, #k do
res[i] = t[k[i]]
res[i] = t[k[i]]
end
end
Line 1,024: Line 1,026:
if type(k) == 'table' then
if type(k) == 'table' then
if type(v) == 'table' then
if type(v) == 'table' then
for i = 1, len(k) do
for i = 1, #k do
t[k[i]] = v[i]
t[k[i]] = v[i]
end
end
else
else
for i = 1, len(k) do
for i = 1, #k do
t[k[i]] = v
t[k[i]] = v
end
end
Please note that all contributions to The Deadlock Wiki are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see Deadlock:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template

Page included on this page: