【问题标题】:Update the values of multiple keys更新多个键的值
【发布时间】:2012-03-09 17:17:40
【问题描述】:

如果您有一个地图或一组地图,并且希望能够使用一个函数更新多个键的值,那么最惯用的方法是什么?

=> (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})

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

【问题讨论】:

    标签: clojure


    【解决方案1】:

    每当您需要对某些数据迭代地应用 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})
    

    【讨论】:

    • 我想知道是否有办法保持更新的行为,以便丢失的键不会引发空指针异常。 (update-in {} [:test] (fnil inc 0)) {:test 1}
    • 这是一个非常好的答案,并突出了学习 clojure 的一些美妙之处(也是非 lisper 的一些脑筋急转弯)
    • 当你传递 + 10 而不是 inc 时,有没有办法保持 update-in 的行为? (update-vals m [:a :b] + 10) 不起作用
    • @Cotten:你可以传递一个函数来获得你想要的行为(update-vals m1 [:a :b] #(+ 10 %))
    • (defn update-vals [m ks & args] (reduce #(apply update-in % [%2] args) m ks)) 是你想要的
    猜你喜欢
    • 2013-10-20
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 2015-09-25
    • 2014-07-14
    相关资源
    最近更新 更多