Clojure:使用索引为向量中的每个元素调用一个函数

时间:2009-10-30 17:51:46

标签: vector clojure loops

说我有一个矢量:

(def data ["Hello" "World" "Test" "This"])

我想在一个有api的地方填充一张桌子:

(defn setCell
  [row col value]
  (some code here))

那么让以下调用发生的最佳方法是什么:

(setCell 0 0 "Hello")
(setCell 0 1 "World")
(setCell 0 2 "Test")
(setCell 0 3 "This")

我发现以下内容可行:

(let [idv (map vector (iterate inc 0) data)]
  (doseq [[index value] idv] (setCell 0 index value)))

但有没有更快的方法不需要新的临时数据结构idv?

5 个答案:

答案 0 :(得分:27)

只需将索引与数据一起映射,就可以以非常方式的方式获得相同的效果。

(map #(setCell 0 %1 %2) (iterate inc 0) data)

您可能希望将其包含在(doall(doseq中,以便现在进行调用。将无限seq与有限seq一起映射就好了,因为当最短的seq用完时,map将停止。

答案 1 :(得分:27)

游戏有点晚,但访问此页面的人:现在(自clojure 1.2以来)clojure.core中有map-indexed函数。

一个问题(除非我弄错了):没有“pmap”等价,这意味着地图索引计算不能轻易并行化。在这种情况下,我会参考上面提供的解决方案。

答案 2 :(得分:10)

你这样做的方式是惯用的(事实上与clojure.contrib.seq-utils/indexed相同)。如果您真的想避免额外的数据结构,可以这样做:

(loop [data data, index 0]
  (when (seq data)
    (setCell 0 index (first data))
    (recur (rest data) (inc index))))

我会使用你的版本,除非有充分的理由不这样做。

答案 3 :(得分:8)

最好的方法是使用clojure.contrib.seq-utils/indexed,它看起来像这样(使用解构):

(doseq [[idx val] (indexed ["Hello" "World" "Test" "This"])]
  (setCell 0 idx val))

答案 4 :(得分:1)

我做了一个简短的比较选项的性能:

; just some function that sums stuff 
(defn testThis
  [i value]
 (def total (+ total i value)))

; our test dataset. Make it non-lazy with doall    
(def testD (doall (range 100000)))

; time using Arthur's suggestion
(def total 0.0)
(time (doall (map #(testThis %1 %2) (iterate inc 0) testD)))
(println "Total: " total)

; time using Brian's recursive version
(def total 0.0)
(time (loop [d testD i 0]
  (when (seq d)
    (testThis i (first d))
    (recur (rest d) (inc i)))))
(println "Total: " total)

; with the idiomatic indexed version
(def total 0.0)
(time (let [idv (map vector (iterate inc 0) testD)]
  (doseq [[i value] idv] (testThis i value))))
(println "Total: " total)

我的1核笔记本电脑的结果:

   "Elapsed time: 598.224635 msecs"
   Total:  9.9999E9
   "Elapsed time: 241.573161 msecs"
   Total:  9.9999E9
   "Elapsed time: 959.050662 msecs"
   Total:  9.9999E9

初步结论:

使用循环/重复解决方案。