Created
December 27, 2019 01:53
-
-
Save Elmuti/b66d7fb289095fb5faa7a84546d5fd42 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local random = Random.new() | |
local Array = {} | |
-- can optionally create an Array from an array-like table | |
function Array.new(tbl) | |
local array = { | |
length = 0, | |
data = {} | |
} | |
if (tbl) then | |
if (type(tbl) == "table") then | |
for k, v in ipairs(tbl) do | |
table.insert(array.data, k, v) -- only inserting the array part of the given table, discards hashtable | |
array.length = array.length + 1 | |
end | |
else | |
error("Invalid argument: tbl in Array.new") | |
end | |
end | |
local newArray = setmetatable(array, Array) | |
return newArray | |
end | |
function Array.from(...) | |
return Array.new({...}) | |
end | |
--Convert array to table | |
function Array:ToTable() | |
return self.data | |
end | |
function Array.Iterator(arr) | |
local i = 0 | |
local n = table.getn(arr.data) | |
return function() | |
i = i + 1 | |
if i <= n then return i, arr.data[i] end | |
end | |
end | |
-- Put one or more elements at the end of the array | |
function Array:Push(...) | |
for _, element in ipairs({...}) do | |
table.insert(self.data, self.length + 1, element) -- length + 1 to avoid 0 index (lua starts at 1) | |
self.length = self.length + 1 | |
end | |
end | |
-- Remove an element from end of the array and return it | |
function Array:Pop() | |
self.length = self.length - 1 | |
return table.remove(self.data) | |
end | |
function Array:Remove(index) | |
assert(index > 0 and index < self.length + 1, "invalid index") | |
self.length = self.length - 1 | |
return table.remove(self.data, index) | |
end | |
-- Applies callback(value, key) to each element of the array | |
function Array:ForEach(callback) | |
assert(callback and typeof(callback) == "function", "Array:Foreach callback needs to be a function") | |
for key, value in ipairs(self.data) do | |
callback(value, key) | |
end | |
end | |
-- Returns a new Array instance which contains only the elements which pass the callback function | |
-- callback(value, key) returns true if the element should be included or false (it's a predicate) | |
function Array:Filter(callback) | |
local filtered = Array.new() | |
for key, value in ipairs(self.data) do | |
if (callback(value, key)) then | |
filtered:Push(value) | |
end | |
end | |
return filtered | |
end | |
function Array:Map(callback) | |
local result = Array.new() | |
for key, value in ipairs(self.data) do | |
result:Push(callback(value, key)) | |
end | |
return result | |
end | |
-- The reducer takes the following arguments: (accumulator, currentValue, currentIndex) | |
-- If no initial value is supplied for the accumulator, the first element of the array is used, and skipped | |
function Array:Reduce(reducer, initial) | |
local acc = initial or self.data[1] | |
local arr = initial and self or self:Copy() | |
if not initial then | |
arr:Remove(1) -- use first element as initial if none provided, and skip first when iterating | |
end | |
for key, value in ipairs(arr.data) do | |
acc = reducer(acc, value, key) | |
end | |
return acc | |
end | |
-- Returns the value which matches the predicate, and also the index of that value | |
function Array:Find(callback) | |
for key, value in ipairs(self.data) do | |
if callback(value) then | |
return value, key | |
end | |
end | |
return nil, nil | |
end | |
function Array:Copy() | |
return Array.from(self:Spread()) | |
end | |
--Returns a random value in the array | |
--Usage: array:Random( [ Random rand ] ) | |
function Array:Random(rand) | |
rand = rand or random | |
return self.data[rand.NextInteger(1, self.length)] | |
end | |
-- Returns a string containing all the elements of the array separated by the separator, default ", " | |
function Array:Join(separator) | |
separator = separator or ", " | |
return table.concat(self.data, separator) | |
end | |
-- Returns true if every element in the array matches the predicate | |
function Array:Every(predicate) | |
for key, value in ipairs(self.data) do | |
if (not predicate(value, key)) then | |
return false | |
end | |
end | |
return true | |
end | |
-- Returns true if at least one element in the array matches the predicate | |
function Array:Some(predicate) | |
for key, value in ipairs(self.data) do | |
if (predicate(value, key)) then | |
return true | |
end | |
end | |
return false | |
end | |
-- Returns a new array which contains all of the given array appended to the end of the current array | |
function Array:Concat(other) | |
local result = self:Copy() | |
result:Push(other:Spread()) | |
return result | |
end | |
function Array:Spread() | |
return table.unpack(self.data) | |
end | |
-- Returns true if the other array is equal to this one | |
function Array:Equals(other) | |
if self == other then | |
return true | |
end | |
for k, v in ipairs(other.data) do | |
if self.data[k] ~= v then | |
return false | |
end | |
end | |
return true | |
end | |
function Array.__index(array, index) | |
if index == "Length" then | |
return rawget(array, "length") | |
else | |
if typeof(index) == "number" then | |
return rawget(array.data, index) | |
else | |
return rawget(Array, index) | |
end | |
end | |
end | |
function Array.__newindex(array, key, value) | |
assert(type(key) == "number", "array indexes can only be numbers") | |
rawset(array.data, key, value) | |
array.length = #array.data | |
end | |
function Array.__tostring(array) | |
return string.format("[%s]", array:Join(", ")) | |
end | |
-- Not in 5.1 | |
--function Array.__len(array) | |
-- return array.length | |
--end | |
-- Nice meme roblox lua 5.1 doesnt have __ipairs and __pairs | |
--function Array.__ipairs(array) | |
-- local function StatelessIterator(arr, idx) | |
-- print("calling stateless iterator", arr, idx) | |
-- idx = idx + 1 | |
-- local value = arr[idx] | |
-- if (value) then | |
-- return idx, value | |
-- end | |
-- end | |
-- print("returning stateless itr") | |
-- | |
-- return StatelessIterator, array, 0 | |
--end | |
-- | |
--function Array.__pairs(array) | |
-- error("Only use ipairs() on Array") | |
--end | |
return Array |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment