You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.2 KiB
Lua

--- Module for a data container that does not allow nil values.
-- @classmod lqc.helpers.vector
-- @alias Vector
local deep_equals = require 'lqc.helpers.deep_equals'
local Vector = {}
local Vector_mt = {
__index = Vector,
}
--- Constructs a new vector, possibly filled with data (a table value)
-- @param data[opt={}] the data to be stored in the vector initially
-- @return a new vector filled with the initial data if provided.
function Vector.new(data)
local begin_data = data or {}
local vector = {
data = begin_data,
}
return setmetatable(vector, Vector_mt)
end
--- Adds an element to the back of the vector.
-- @param obj a non-nil value
-- @return self (for method chaining); raises an error if trying to add nil to the vector
function Vector:push_back(obj)
if obj == nil then
error 'nil is not allowed in vector datastructure!'
end
table.insert(self.data, obj)
return self
end
--- Replaces an element in the vector.
-- @param idx Index of the element in the vector to be replaced
-- @param obj Object that the previous object should be replaced with
-- @return self (for method chaining); raises an error if idx is an index
-- not present in the vector
function Vector:replace(idx, obj)
local vec_size = self:size()
if idx < 1 or idx > vec_size then
error('Invalid index! Index should be between 1 and ' .. vec_size)
end
self.data[idx] = obj
return self
end
--- Appends another vector to this vector
-- @param other_vec Another vector object
-- @return a vector containing the data of both vectors
function Vector:append(other_vec)
for i = 1, other_vec:size() do
self:push_back(other_vec:get(i))
end
return self
end
--- Gets the element at position 'index' in the vector
-- @param index position of the value in the vector
-- @return element at position 'index
function Vector:get(index)
return self.data[index]
end
--- Checks if an element is contained in the vector
-- @param element element to be checked if it is in the vector
-- @return true if the element is already in the vector; otherwise false.
function Vector:contains(element)
for i = 1, #self.data do
if self.data[i] == element then
return true
end
end
return false
end
--- Returns the size of the vector.
-- @return length of the vector (0 if empty)
function Vector:size()
return #self.data
end
--- Removes an element from the vector by value
-- @param obj object to remove
function Vector:remove(obj)
-- Find element, then remove by index
local pos = -1
for i = 1, #self.data do
if deep_equals(self.data[i], obj) then
pos = i
break
end
end
if pos == -1 then
return
end
table.remove(self.data, pos)
end
--- Removes an element from the vector by index
-- @param idx Position of the element you want to remove
function Vector:remove_index(idx)
if idx > self:size() then
return
end
table.remove(self.data, idx)
end
--- Returns the vector, with the contents represented as a flat table
-- @return Table with the contents of the vector
function Vector:to_table()
return self.data
end
return Vector