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

时间:2010-03-01 22:50:43

标签: clojure

假设:

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

如何迭代每个元素来打印该元素:a和所有的总和:b到那个点?那就是:

“foo”10
“酒吧”23
“baz”30

我正在尝试这样的事情无济于事:

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

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

TIA!肖恩

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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:什么是获得滚动金额的更好方法?

答案 2 :(得分: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])