Say I have a vector:
(def data ["Hello" "World" "Test" "This"])
And I want to populate a table somewhere that has an api:
(defn setCell
[row col value]
(some code here))
Then what is the best way to get the following calls to happen:
(setCell 0 0 "Hello")
(setCell 0 1 "World")
(setCell 0 2 "Test")
(setCell 0 3 "This")
I found that the following will work:
(let [idv (map vector (iterate inc 0) data)]
(doseq [[index value] idv] (setCell 0 index value)))
But is there a faster way that does not require a new temporary datastructure idv?
You can get the same effect in a very clojure-idiomatic way by just mapping the indexes along with the data.
(map #(setCell 0 %1 %2) (iterate inc 0) data)
You may want to wrap this in a (doall
or (doseq
to make the calls happen now. It's just fine to map an infinite seq along with the finite one because map will stop when the shortest seq runs out.
A bit late in the game but for people accessing this page: there is now (since clojure 1.2) a map-indexed
function available in clojure.core.
One issue (unless I'm mistaken): there's no "pmap" equivalent, meaning that map-indexed computations cannot easily be parallelized. In that case, I'd refer to solutions offered above.
The way you're doing it is idiomatic (and identical to clojure.contrib.seq-utils/indexed
in fact). If you really want to avoid the extra data structure, you can do this:
(loop [data data, index 0]
(when (seq data)
(setCell 0 index (first data))
(recur (rest data) (inc index))))
I'd use your version unless there was a good reason not to though.
The nicest way would be to use clojure.contrib.seq-utils/indexed
, which will look like this (using destructuring):
(doseq [[idx val] (indexed ["Hello" "World" "Test" "This"])]
(setCell 0 idx val))
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