Custom array class

Yesterday, I was experimenting with metatables and managed to make my own Array class. So far, this is what I got.

Class code:

local Array2 = {};
Array2.__index = Array2;

-- [methods] --

-- adds value to end of array
function Array2.__index:Push(value)
	self[#self+1] = value;
end

-- removes value from end of array. returns that value
-- prameters: none
function Array2.__index:Pop()
	return table.remove(self,#self);
end

-- adds value to start of array
-- prameters: value to insert
function Array2.__index:Insert(value)
	table.insert(self,1,value);
end

-- removes value from start of array. returns that value
-- prameters: none
function Array2.__index:Remove()
	return table.remove(self,1);
end

-- loops through array and runs a function each iteration
-- prameters: function with array value as a pramater
function Array2.__index:ForEach(fun)
	for i,v in ipairs(self) do
		fun(v);
	end
end

-- returns a new array from an old one, with filtered values
-- pramaters: function with array value as a prameter
function Array2.__index:Filter(fun)
	local newArray = {};
	for i,v in ipairs(self) do
		if fun(v) == true then
			table.insert(newArray,#newArray,v);
		end
	end
	return newArray;
end

-- returns a boolean which determines if only some array values are equal to a value you choose
-- prameters: value to check for
function Array2.__index:Some(value)
	local newArray = {};
	for i,v in ipairs(self) do
		if v == value then
			newArray[#newArray+1] = v;
		end
	end
	if #newArray == #self then return false; end
	return true;
end

-- works the same as the Some method, only it checks if ALL values are equal to a value you choose
-- prameters: value to check for
function Array2.__index:All(value)
	local newArray = {};
	for i,v in ipairs(self) do
		if v == value then 
			newArray[#newArray+1] = v;
		end
	end
	if #newArray == #self then return true; end
	return false;
end

-- returns the length of the array
function Array2.__index:Length()
	return #self;
end

-- return the index of the given value, otherwise nil if it doesn't exist
-- prameters: values to check for, index to start at (optional. defaults to 1 if nil)
function Array2.__index:Find(value,init) 
	if init == nil then init = 1; end
	for i = init,#self,1 do
		if self[i] == value then
			return i;
		end
	end
	
	return nil;
end

-- [init] --

function Array2.new()
	return setmetatable({},Array2);
end

return Array2;

Example usage:

local Array2 = require(script.Array2);

local newArray = Array2.new(); -- create the array


newArray:Push("Foo");
newArray:Push("Foo");
newArray:Push(1);
newArray:Push(false);

newArray:Insert(workspace.Baseplate);

newArray:ForEach(function(value)
	print("Value: ",value);
end)

local stringOnlyArray = newArray:Filter(function(value)
	return typeof(value) == "string";
end)

local instanceOnlyArray = newArray:Filter(function(value)
	return typeof(value) == "Instance";
end)

print(stringOnlyArray); -- {"Foo","Foo"}
print(instanceOnlyArray); --{Baseplate}

print(newArray:Find(false)); -- prints index of value
print(newArray:Some("Foo")); -- true
print(newArray:All("Foo")); -- false
print(newArray:Length()); -- 5

newArray:Remove();

print(newArray:Find(workspace.Baseplate)) -- nil

Interesting stuff.
The code is a little janky though. You don’t really need to reference Array2.__index everytime you want to add a new function because Array2.__index is just Array2.

Another thing you probably want to also pass the index into the callback function in the ForEach method.

1 Like

Thanks!

I already know that Array2.__index refers to itself, I just like to add it because I think it looks better documented.

Yeah, I should probably add the index to the callback function.

1 Like