Clojure nested map - change value

前端 未结 2 711
说谎
说谎 2021-01-01 18:06

have to say I started learning Clojure about two weeks ago and now I\'m stuck on a problem since three full days.

I got a map like this:

{
  :agent1          


        
相关标签:
2条回答
  • 2021-01-01 18:47

    assoc-in is used for replacing or inserting values in the map specified by path

    (def m { :agent1 {:name "Doe" :firstname "John" :state "a" :time "VZ" :team "X"}
             :agent2 {:name "Don" :firstname "Silver" :state "a" :time "VZ" :team "X"}
             :agent3 {:name "Kim" :firstname "Test" :state "B" :time "ZZ" :team "G"}})
    
    (assoc-in m [:agent1 :team] "H")
    
    {:agent1 {:state "a", :team "H", :name "Doe", :firstname "John", :time "VZ"},
     :agent2 {:state "a", :team "X", :name "Don", :firstname "Silver", :time "VZ"},
     :agent3 {:state "B", :team "G", :name "Kim", :firstname "Test", :time "ZZ"}}
    

    however, if you want to update ALL team "X"'s, regardless of specific path, over all recursive levels of the tree, you can use clojure.walk's prewalk or postwalk functions combined with a function of your own:

    (use 'clojure.walk)
    (defn postwalk-mapentry
        [smap nmap form]
        (postwalk (fn [x] (if (= smap x) nmap x)) form))
    
    (postwalk-mapentry [:team "X"] [:team "T"] m)
    
    {:agent1 {:state "a", :team "T", :name "Doe", :firstname "John", :time "VZ"},
     :agent2 {:state "a", :team "T", :name "Don", :firstname "Silver", :time "VZ"},
     :agent3 {:state "B", :team "G", :name "Kim", :firstname "Test", :time "ZZ"}}
    
    0 讨论(0)
  • 2021-01-01 18:53

    The walking functions are good for replacement like that.

    (clojure.walk/prewalk-replace {[:team "X"] [:team "H"]} map)

    Passing in vectors allows you to ensure that you don't just replace all the "X"s.

    0 讨论(0)
提交回复
热议问题