(Lisp beginner) I need to create a 2D array, and initialize each cell in the array. Each cell is initialized with a function that is based on data in a preceding cell. So the cell as 0,1 will be initialized with the result of a function that uses the data from cell 0,0, and so on.
I was wondering what is the proper clojure idiom for setting up a data structure like this.
Representation of your array actually depends on you needs of using it, not initializing it. For example, if you have dense matrix, you most probably should use vector of vectors like this:
[[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[9, 8, 7, 6, 5],
[4, 3, 2, 1, 0],
[0, 1, 2, 3, 4]]
or single vector with some additional info on raw length:
{:length 5
:data
[0, 1, 2, 3, 4,
5, 6, 7, 8, 9,
9, 8, 7, 6, 5,
4, 3, 2, 1, 0,
0, 1, 2, 3, 4]
}
and if you need sparse matrix, you can use hash-map
s:
{0 {0 0, 4 4},
2 {2 7},
3 {0 4, 2 2}}
(since your 2D array is small and you generate next value based on previous one, I believe first option is better suited for you).
If you are going to make a lot of matrix-specific manipulations (multiplication, decomposition, etc) you may want to use some existing libraries like Incanter.
And as for filling, my proposal is to use transients and store interim results, i.e. (for one-dimensional vector):
(defn make-array [initial-value f length]
(loop [result (transient []), length-left length, interim-value initial-value]
(if (= length-left 0)
(persistent! result)
(recur (conj! result (f interim-value)) (- length-left 1) (f interim-value))))
Transients will avoid creating new data structure on each new element, and interim value will avoid need in reading previous element from transient structure.
I don't know if this is a bad technique but I've used hash (or usually ordered) maps to specify 2D "arrays". They build up like this:
{ [x y] value ... }
There are cons to this since you have to specify the limits of the array somehow. And probably it's very slow compared to straight vector presentations as described in ffriend's post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With