doc | ||
src/sparse_array | ||
test/sparse_array | ||
.gitignore | ||
CHANGELOG.md | ||
LICENSE | ||
project.clj | ||
README.md |
sparse-array
A Clojure library designed to manipulate sparse arrays - multi-dimensional spaces accessed by indices, but containing arbitrary values rather than just numbers. For sparse spaces which contain numbers only, you're better to use a sparse matrix library, for example clojure.core.matrix.
Arbitrary numbers of dimensions are supported, up to limits imposed by the JVM stack.
Conventions:
Sparse arrays
For the purposes of this library, a sparse array shall be implemented as a map, such that all keys are non-negative members of the set of integers, except for the following keyword keys, all of which are expected to be present:
:dimensions
The number of dimensions in this array, counting the present one (value expected to be a real number);:coord
The coordinate of the dimension represented by the current map (value expected to be a keyword);:content
What this map contains; if the value of:dimensions
is one, then:data
; otherwise, an ordered sequence of the coordinates of the dimensions below this one.
Thus an array with a single value 'hello' at coordinates x = 3, y = 4, z = 5 would be encoded:
{:dimensions 3
:coord :x
:content [:y :z]
3 {:dimensions 2
:coord :y
:content [:z]
4 {:dimensions 1
:coord :z
:content :data
5 "hello"
}
}
}
At the present stage of development, where the expectations of an operation are violated, nil
is returned and no exception is thrown. However, it's probable that later there will be at least the option of thowing specific exceptions, as otherwise debugging could be tricky.
Dense arrays
For the purposes of conversion, a dense array is assumed to be a vector; a two dimensional dense array a vector of vectors; a three dimensional dense array a vector of vectors of vectors, and so on. For any depth N
, all vectors at depth N
must have the same arity. If these conventions are not respected conversion may fail.
Usage
make-sparse-array
sparse-array.core/make-sparse-array ([& dimensions])
Make a sparse array with these dimensions
. Every member of dimensions
must be a keyword; otherwise, nil
will be returned.
e.g.
(make-sparse-array :x :y :z)
=> {:dimensions 3, :coord :x, :content (:y :z)}
sparse-array?
sparse-array.core/sparse-array? ([x])
true
if x
is a sparse array conforming to the conventions established by this library, else false
.
put
sparse-array.core/put ([array value & coordinates])
Return a sparse array like this array
but with this value
at these coordinates
. Returns nil
if any coordinate is invalid.
e.g.
(put (put (make-sparse-array :x :y) "hello" 3 4) "goodbye" 4 3)
=> {:dimensions 2,
:coord :x,
:content (:y),
3 {:dimensions 1, :coord :y, :content :data, 4 "hello"},
4 {:dimensions 1, :coord :y, :content :data, 3 "goodbye"}}
get
sparse-array.core/get ([array & coordinates])
Return the value in this sparse array
at these coordinates
.
merge-sparse-arrays
sparse-array.core/merge-sparse-arrays ([a1 a2])
Return a sparse array taking values from sparse arrays a1
and a2
, but preferring values from a2
where there is a conflict. a1
and a2
must have the same dimensions in the same order, or nil
will be returned.
e.g.
(merge-sparse-arrays
(put (make-sparse-array :x) "hello" 3)
(put (make-sparse-array :x) "goodbye" 4)))
=> {:dimensions 1, :coord :x, :content :data, 3 "hello", 4 "goodbye"}
dense-to-sparse
sparse-array.core/dense-to-sparse ([x] [x coordinates])
Return a sparse array representing the content of the dense array x
, assuming these coordinates
if specified. NOTE THAT if insufficient values of coordinates
are specified, the resulting sparse array will be malformed.
e.g.
(dense-to-sparse [nil nil nil "hello" nil "goodbye"])
=> {:dimensions 1, :coord :i0, :content :data, 3 "hello", 5 "goodbye"}
sparse-to-dense
sparse-array.core/sparse-to-dense ([x] [x arity])
Return a dense array representing the content of the sparse array x
.
NOTE THAT this has the potential to consume very large amounts of memory.
e.g.
(sparse-to-dense
(put
(put
(make-sparse-array :x :y)
"hello" 3 4)
"goodbye" 4 3))
=> [[nil nil nil nil nil]
[nil nil nil nil nil]
[nil nil nil nil nil]
[nil nil nil nil "hello"]
[nil nil nil "goodbye" nil]]
License
Copyright © 2019 Simon Brooke
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.