5

(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.

3
  • Could you add an example "array" (probably Clojure vector would be more appropriate) that shows exactly how you want to apply your functions? Doing something to 0,1 based on 0,0 means your just dealing with a single-dimensional array within a larger 2d one; did you mean 0,0 would affect 1,0 etc.? Commented Mar 3, 2011 at 15:36
  • Its a 5x5 array, with the value of each cell calculated with a preceding cell. The first cell (0,0) has the value 1. The cell at (0,1) has the value of f(x) -> y (x is the contents of 0,0). Not all cells have the same function to generate their value, but all functions has a single parameter, the value of a previously initialized cell. Commented Mar 3, 2011 at 15:42
  • don't forget to use '@<username>', so a person you address to gets notified about your comment. Commented Mar 3, 2011 at 16:35

2 Answers 2

11

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-maps:

{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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

1 Comment

I use this in Python when I know that my "array" has many holes in it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.