2012-03-09 85 views
13

如果您有一张地图或一组地图,并且您希望能够使用一个功能更新多个键的值,那么执行此操作最常用的方法是什么?更新多个键的值

=> (def m [{:a 2 :b 3} {:a 2 :b 5}]) 
#'user/m 
=> (map #(update-in % [:a] inc) m) 
({:a 3, :b 3} {:a 3, :b 5}) 

不是映射更新,在每个关键,我最想要的,经营一些像这样的功能:

=> (map #(update-vals % [:a :b] inc) m) 
({:a 3, :b 4} {:a 3, :b 6}) 

任何建议,将不胜感激!我试图减少不必要的长脚本中的行数。

回答

22

当你需要一个FN反复应用到一些数据,reduce是你的朋友:

(defn update-vals [map vals f] 
    (reduce #(update-in % [%2] f) map vals)) 

这是在行动:

user> (def m1 {:a 2 :b 3}) 
#'user/m1 
user> (update-vals m1 [:a :b] inc) 
{:a 3, :b 4} 
user> (def m [{:a 2 :b 3} {:a 2 :b 5}]) 
#'user/m 
user> (map #(update-vals % [:a :b] inc) m) 
({:a 3, :b 4} {:a 3, :b 6}) 
+1

非常好,快速回复太感谢了! – Giles 2012-03-09 20:11:20

+0

我想知道是否有办法保持update-in的行为,以便丢失的键不会抛出空指针异常。 '(update-in {} [:test](fnil inc 0)) {:test 1}' – Istvan 2014-05-01 18:47:27

+0

这是一个很好的答案,并强调了一些学习clojure的美丽(也包括一些大脑包装困难non-lisper) – zach 2014-05-28 19:49:57