17

私は約2週間前にClojureを学び始めましたが、今では丸3日から問題に悩まされています。

私はこのような地図を手に入れました:

{
  :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"}
}

に変更:team "X"する必要があり:team "H"ます。assocなど、いろいろ試してみましたが、update-inうまくいきません。

どうすれば自分の仕事をすることができますか?どうもありがとう!

4

2 に答える 2

20

assoc-in は、パスで指定されたマップ内の値を置換または挿入するために使用されます

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

ただし、特定のパスに関係なく、ツリーのすべての再帰レベルですべてのチーム「X」を更新する場合は、clojure.walk の prewalk または postwalk 関数を独自の関数と組み合わせて使用​​できます。

(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"}}
于 2012-07-20T11:25:45.917 に答える
12

ウォーキング機能は、そのような交換に適しています。

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

ベクトルを渡すことで、すべての「X」を置き換えるだけではないことを確認できます。

于 2012-07-20T11:57:22.190 に答える