Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Elmuti
Created December 27, 2019 01:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Elmuti/b66d7fb289095fb5faa7a84546d5fd42 to your computer and use it in GitHub Desktop.
Save Elmuti/b66d7fb289095fb5faa7a84546d5fd42 to your computer and use it in GitHub Desktop.
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