更新内部减少矢量

时间:2017-07-18 05:14:04

标签: clojure

给出一个向量:

(def vec [{:key 1, :value 10, :other "bla"}, {:key 2, :value 13, :other "bla"}, {:key 1, :value 7, :other "bla"}])

我想迭代每个元素并使用所有:value的总和更新:value到那一点,所以我会:

[{:key 1, :value 10, :other "bla"}, {:key 2, :value 23, :other "bla"}, {:key 1, :value 30, :other "bla"}])

我发现this用于打印结果,但我尝试在下面的代码中将prn命令更改为update-inassoc-in(从中提取上面的链接)但我没有很好地工作。

(reduce (fn [total {:keys [key value]}]
                  (let [total (+ total value)]
                    (prn key total)
                    total))
              0 vec)

我是Clojure的新手,我怎样才能让它发挥作用?

2 个答案:

答案 0 :(得分:2)

如果您想获得正在运行的总数,那么最简单的方法是使用reductions

(reductions (fn [acc ele] (+ acc (:value ele))) 
            0
            [{:key 1, :value 10, :other "bla"}, {:key 2, :value 13, :other "bla"}, {:key 1, :value 7, :other "bla"}])
;; => (0 10 23 30)

正如您所看到的,传递给reductions的函数与传递给reduce的函数具有相同的签名。就像你要求每次到达新元素时都要完成reduce。考虑它的另一种方式是,每次计算新的累加器时都会保留它,与reduce不同,调用者只能看到最后一次计算的结果。

所以这是直接回答你问题的代码:

(->> [{:key 1, :value 10, :other "bla"}, {:key 2, :value 13, :other "bla"}, {:key 1, :value 7, :other "bla"}]
     (reductions #(update %2 :value + (:value %1))
                 {:value 0})
     next
     vec)
;; => [{:key 1, :value 10, :other "bla"} {:key 2, :value 23, :other "bla"} {:key 1, :value 30, :other "bla"}]

答案 1 :(得分:1)

您可以累积:value s:

(reductions + (map :value v))
=> (10 23 30)

(我重命名了向量v以避免绊倒clojure.core/vec。)

然后,您可以mapv使用assoc

(let [value-sums (reductions + (map :value v))]
  (mapv #(assoc %1 :value %2) v value-sums))
=> [{:key 1, :value 10, :other "bla"} {:key 2, :value 23, :other "bla"} {:key 1, :value 30, :other "bla"}]