2010-03-01 45 views
4

考虑:如何操作矢量中的每个项目并参考Clojure中的前一个值?

(def my-vec [{:a "foo" :b 10} {:a "bar" :b 13} {:a "baz" :b 7}]) 

怎么会遍历每个元素打印元素:一个和所有的总和:B的那个点?那就是:

“FOO” 10
“栏中的” 23
“巴兹” 30

我想这样的事情无济于事:

; Does not work!  
(map #(prn (:a %2) %1) (iterate #(+ (:b %2) %1) 0)) my-vec) 

这不起作用因为“iterate”lazy-seq无法引用my-vec中的当前元素(据我所知)。

TIA! Sean

+0

[删除评论] – 2010-03-01 23:48:50

回答

6
user> (reduce (fn [total {:keys [a b]}] 
        (let [total (+ total b)] 
        (prn a total) 
        total)) 
       0 my-vec) 
"foo" 10 
"bar" 23 
"baz" 30 
30 
+0

超级优雅。感谢Brian! :) – scrotty 2010-03-02 00:14:30

1

你可以把它看作从一系列映射开始,过滤出一系列:a值和b值滚动和的单独序列,然后将两个参数的函数映射到两个派生序列。

创建的只是顺序:a和:B值与

(map :a my-vec) 
(map :b my-vec) 

然后一个函数来获取滚动总和:

(defn sums [sum seq] 
    "produce a seq of the rolling sum" 
    (if (empty? seq) 
     sum 
     (lazy-seq 
     (cons sum 
       (recur (+ sum (first seq)) (rest seq)))))) 

然后把它们放在一起:

(map #(prn %1 %s) (map :a my-vec) (sums 0 (map :b my-vec))) 

分开处理数据产生的问题。希望这会让生活更轻松。

PS:最好的方式获得滚动的总和?

+0

接听PS:尽量' clojure.contrib.seq/reductions'。 – 2010-03-02 00:12:55

+0

谢谢你,亚瑟。我喜欢分离数据的想法。 – scrotty 2010-03-02 00:14:07

0

将其转换为总结顺序:

(defn f [start mapvec] 
    (if (empty? mapvec) '() 
     (let [[ m & tail ] mapvec] 
      (cons [(m :a)(+ start (m :b))] (f (+ start (m :b)) tail))))) 

古称:

(f 0 my-vec) 

回报:

(["foo" 10] ["bar" 23] ["baz" 30]) 
相关问题