array_vector v0.3.0 Vector
Functions that work on vectors.
This datastructure wraps Erlang’s array
type for fast random
lookup and update to large collections.
The point of this module is not meant to be a 1:1 wrapper, but to be a useful set of higher-level API operations.
Note that this module is implemented as a struct with an array
field,
pointing to the underlying Erlang array
implementation. This field
is private, so you should use the functions in this module
to perform operations.
Link to this section Summary
Functions
Append an item to to a vector
Returns the count of initialized elements in the vector. Does not count uninitialized elements. This function takes time linear to the number of uninitialized elements
Returns either the vector without the value at index, or the original vector if no value is present at index
Finds the element at the given index
(zero-based) in logarithmic time.
Returns {:ok, element}
if found, otherwise :error
Finds the element at the given index
(zero-based) in logarithmic time
Gets the value at an index in logarithmic time, returning a default if it does not exist
Gets and updates a value at the same time
Run a function over the elements of the vector, not including the uninitialized ones, and return the result in a new vector. Good for large vectors where only a few elements are set
Checks if vector
contains value
Constructs a array-backed vector
Deletes a value at index, returning the new vector and the value that was deleted
Puts the given value under index in vector in logarithmic time
Run a function (fun
) over a vector which takes two arguments: the accumulated results so far (acc
) and the current vector value (val
).
Hits only the initialized elements of the vector. Note that fun
is arity-3, taking the index
, value
, and acc
in that order
Reverse every element in a vector, not including the uninitialized elements.
Preserves count
, does not preserve size
Returns the total size of a vector, including all uninitialized/default values
Converts a vector
to a list
Updates the value in vector with the given function in logarithmic time
Updates index with the given function in logarithmic time
Link to this section Types
Link to this section Functions
Append an item to to a vector
Examples
iex> Vector.new([1, 2, 3]) |> Vector.append(9)
Vector.new([1, 2, 3, 9])
iex> Vector.new() |> Vector.append("hi")
Vector.new(["hi"])
iex> Vector.new([1, 2, 3]) |> Vector.append(9) |> Vector.size
4
Returns the count of initialized elements in the vector. Does not count uninitialized elements. This function takes time linear to the number of uninitialized elements.
Examples
iex> Vector.count(Vector.new())
0
iex> Vector.count(Vector.new([1,2,3,4,5]))
5
iex> Vector.new(100) |> Vector.count
0
iex> Vector.new(100)
...> |> Vector.put(43, 1)
...> |> Vector.count
1
Returns either the vector without the value at index, or the original vector if no value is present at index.
Examples
iex> Vector.delete(Vector.new([1,2,3,4,5]), 2)
#Vector<[1, 2, 4, 5]>
iex> Vector.delete(Vector.new([1,2,3]), 9)
#Vector<[1, 2, 3]>
Finds the element at the given index
(zero-based) in logarithmic time.
Returns {:ok, element}
if found, otherwise :error
.
A negative index can be passed, in which case the index is counted from the end (e.g. -1 finds the last element).
Examples
iex> Vector.fetch(Vector.new([1,2,3]), 9)
:error
iex> Vector.fetch(Vector.new([1,2,3]), 2)
{:ok, 3}
iex> Vector.fetch(Vector.new([1,2,3,4,5]), -2)
{:ok, 4}
iex> Vector.fetch(Vector.new([1,2,3,4,5]), -6)
:error
Finds the element at the given index
(zero-based) in logarithmic time.
Raises OutOfBoundsError
if the given index
is outside the range of
the enumerable.
A negative index can be passed, in which case the index is counted from the end (e.g. -1 finds the last element).
Examples
iex> Vector.fetch!(Vector.new([1,2,3]), 1)
2
iex> Vector.fetch!(Vector.new([1,2,3]), -1)
3
iex> Vector.fetch!(Vector.new([1,2,3]), 99)
** (Enum.OutOfBoundsError) out of bounds error
Gets the value at an index in logarithmic time, returning a default if it does not exist.
Examples
iex> Vector.get(Vector.new([1,2,3]), 0)
1
iex> Vector.get(Vector.new([1,2,3]), 9)
nil
iex> Vector.get(Vector.new([1,2,3]), 9, 1000)
1000
Gets and updates a value at the same time.
Examples
iex> {val, new_vector} = Vector.get_and_update(Vector.new([1,2,3]), 0, fn(value) -> {value, value + 100} end)
iex> {val, Vector.to_list(new_vector)}
{1, [101, 2, 3]}
iex> {val, new_vector} = Vector.get_and_update(Vector.new([1,2,3]), 0, fn(_) -> :pop end)
iex> {val, Vector.to_list(new_vector)}
{1, [2, 3]}
Run a function over the elements of the vector, not including the uninitialized ones, and return the result in a new vector. Good for large vectors where only a few elements are set.
Examples
iex> Vector.new() |> Vector.map(fn(_i, val) -> val + 1 end)
#Vector<[]>
iex> Vector.new([1, 2, 3]) |> Vector.map(fn(_i, val) -> val + 1 end)
#Vector<[2, 3, 4]>
iex> Vector.new(100) |> Vector.map(fn(_i, _val) -> 1 end) |> Enum.sum
0
Checks if vector
contains value
Examples
iex> Vector.member?(Vector.new([1,2,3]), 99)
false
iex> Vector.member?(Vector.new([1,2,3]), 2)
true
Constructs a array-backed vector
Examples
iex> Vector.new()
#Vector<[]>
iex> Vector.new(Vector.new())
#Vector<[]>
iex> Vector.new([1,2,3])
#Vector<[1, 2, 3]>
iex> Vector.new(%{a: 1, b: 2})
#Vector<[a: 1, b: 2]>
iex> Vector.new(0)
#Vector<[]>
# this is exposing a bit of implementation, but I am
# unsure how else to test it
iex> Vector.new(5).array
{:array, 5, 10, :undefined, 10}
Deletes a value at index, returning the new vector and the value that was deleted
Examples
iex> {value, new} = Vector.pop(Vector.new([1,2,3]), 2)
iex> {value, Vector.to_list(new)} # arrays cannot be checked for value equality
{3, [1, 2]}
iex> {value, new} = Vector.pop(Vector.new([1,2,3]), 99)
iex> {value, Vector.to_list(new)}
{nil, [1, 2, 3]}
Puts the given value under index in vector in logarithmic time
A negative index can be passed, in which case the index is counted from the end (e.g. -1 finds the last element).
Examples
iex> Vector.put(Vector.new([1,2,3]), 3, 99)
#Vector<[1, 2, 3, 99]>
iex> Vector.put(Vector.new([1,2,3]), 0, 3)
#Vector<[3, 2, 3]>
iex> Vector.put(Vector.new([1,2,3]), -1, 101)
#Vector<[1, 2, 101]>
iex> Vector.put(Vector.new(3), -99, "hi")
** (ArgumentError) negative index out of bounds
Run a function (fun
) over a vector which takes two arguments: the accumulated results so far (acc
) and the current vector value (val
).
Hits only the initialized elements of the vector. Note that fun
is arity-3, taking the index
, value
, and acc
in that order.
Think of this function as the equivalent of the following pseudocode:
vector |> filter(initialized?) |> reduce
without the intermediate filter, due to sparse folding being an array primitive.
Examples
iex> Vector.new([1, 2, 3]) |> Vector.reduce(0, fn(_index, val, acc) -> val + acc end)
6
iex> Vector.new([1, 2, 3]) |> Vector.reduce(Vector.new(), fn(_index, val, acc) -> Vector.append(acc, val + 1) end)
#Vector<[2, 3, 4]>
iex> Vector.new(100)
...> |> Vector.put(25, 1)
...> |> Vector.put(50, 1)
...> |> Vector.put(75, 1)
...> |> Vector.put(90, 1)
...> |> Vector.reduce(0, fn(_index, val, acc) -> acc + val end)
4
Reverse every element in a vector, not including the uninitialized elements.
Preserves count
, does not preserve size
.
Examples
iex> vector = Vector.new([1,2,3])
iex> vector |> Vector.reverse |> Vector.reverse
#Vector<[1, 2, 3]>
iex> Vector.reverse(Vector.new())
#Vector<[]>
iex> Vector.reverse(Vector.new([1, 2, 3]))
#Vector<[3, 2, 1]>
iex> vector = Vector.new(50) |> Vector.put(39, "hi")
iex> reversed = Vector.reverse(vector)
iex> Vector.count(vector) == Vector.count(reversed)
true
Returns the total size of a vector, including all uninitialized/default values.
This function is a reflection of the total memory size of the underlying Erlang array. It does
not say anything about the elements of the array. For a count of non-default elements in the vector,
see count/1
.
Examples
iex> Vector.size(Vector.new())
0
iex> Vector.size(Vector.new([1,2,3,4,5]))
5
iex> Vector.new(100) |> Vector.size
100
iex> Vector.new(100) |> Vector.put(43, 1) |> Vector.size
100
Converts a vector
to a list
Examples
iex> Vector.new() |> Vector.to_list
[]
iex> Vector.to_list(Vector.new([1,2,3]))
[1,2,3]
iex> Vector.new(100) |> Vector.put(39, 1) |> Vector.to_list
[1]
Updates the value in vector with the given function in logarithmic time.
If index is present in vector with value, fun is invoked with argument value and its result is used as the new value of index. If index is not present in vector, initial is inserted as the value of index.
A negative index can be passed, in which case the index is counted from the end (e.g. -1 finds the last element).
Examples
iex> Vector.update(Vector.new([1,2,3]), 0, 13, &(&1 * 2))
#Vector<[2, 2, 3]>
iex> Vector.update(Vector.new([1,2,3]), 5, 11, &(&1 * 2))
#Vector<[1, 2, 3, 11]>
iex> Vector.update(Vector.new([1,2,3]), -2, 11, &(&1 * 2))
#Vector<[1, 4, 3]>
Updates index with the given function in logarithmic time.
If index is present in vector with value, fun is invoked with argument value and its result is used as the new value of index. If index is not present in vector, a Enum.OutOfBoundsError exception is raised.
Examples
iex> Vector.update!(Vector.new([1,2,3]), 0, &(&1 * 2))
#Vector<[2, 2, 3]>
iex> Vector.update!(Vector.new([1,2,3]), 5, &(&1 * 2))
** (Enum.OutOfBoundsError) out of bounds error
iex> Vector.update!(Vector.new([1,2,3]), -2, &(&1 * 2))
#Vector<[1, 4, 3]>