2017-07-18 71 views
1

給定一個向量:更新矢量內減少

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

我想遍歷每個元素,並與所有:value s到該點的總和更新:value,所以我會:

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

我發現this用於打印結果,但我試圖將prn命令更改爲update-in,assoc-in,其代碼如下(從上面的鏈接中提取),但我工作得不太好。

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

我是Clojure的新手,我該如何讓它工作?

回答

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"}] 
+0

'#(更新%2:值+(:值%1))'少':value' – cfrick

+0

由於 - 如果一個'assoc'的RHS指的是什麼* ASSOC-ING *那麼氣味可以通過更新'來代替。現在將做出修復。 –

+0

vec後面還有一個括號,但除此之外,它工作得很好:) – isamendonca

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"}]