Clojure:如何更新映射中的多个值

Clojure:如何更新映射中的多个值,clojure,Clojure,我有一个包含多个计数器的地图,例如: (def m1 (atom {:counter1 10 :counter2 3 :counter3 11})) ;;;=> {:counter1 10, :counter3 11, :counter2 3} 我想将计数器2增加一,并将计数器1和计数器3重置为零 我似乎想不出一个办法来做这件事。我遇到的最好的函数是下面的函数。但是,此函数不会将计数器1和计数器3重置回零,只是不会增加它们 (swap! m1 (fn [m] (m

我有一个包含多个计数器的地图,例如:

(def m1 (atom {:counter1 10 :counter2 3 :counter3 11}))
;;;=> {:counter1 10, :counter3 11, :counter2 3}
我想将计数器2增加一,并将计数器1和计数器3重置为零

我似乎想不出一个办法来做这件事。我遇到的最好的函数是下面的函数。但是,此函数不会将计数器1和计数器3重置回零,只是不会增加它们

(swap! m1 (fn [m]
            (merge-with + m {:counter1 0
                             :counter2 1
                             :counter3 0})))
;;;=> {:counter1 10, :counter3 11, :counter2 4}

是否可以通过一次交换来实现我的要求!,或者我需要通过调用swap来实现!和多次重置

那么,您可以修改代码来完成此操作,方法是将
合并中的
+
替换为另一个函数:

(defn my-plus [old new] (if (pos? new) (+ new old) 0))

我仍在考虑一种不同的解决方法。

保持简单!使用普通的
合并
并再次从地图访问
:counter 2

(swap! m1 (fn [m]
            (merge m {:counter1 0
                      :counter2 (-> m :counter2 inc)
                      :counter3 0})))

或将两个操作分开:

(swap! m1 #(-> % 
           (update :counter2 inc) 
           (assoc :counter1 0 :counter3 0)))
编辑


如果您使用的是<1.7 Clojure版本,请使用迄今为止最惯用的解决方案,而不是。对于(waaay)比这更复杂的转换,可能有用。update是一个单独的函数,它以键和函数(在本例中为inc)作为参数吗?还有一个后续问题,为什么我们不能在assoc中增加:counter2?@sakh1979我添加了更新(-in)文档链接<代码>关联
仅关联值-它不接受函数。使用
assoc
的方法基本上与所建议的@QuickBrownFox相同(
s/merge m{/assoc m/