Clojure вложенная карта - значение изменения

Должен сказать, что я начал изучать Clojure около двух недель назад, и теперь я столкнулся с проблемой с трех полных дней.

У меня есть такая карта:

{
  :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 и т.д., Но ничего не работает.

Как я могу делать свои вещи? Большое вам спасибо!

Ответ 1

Ассоциация используется для замены или вставки значений в карту, указанную путем

(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" независимо от конкретного пути по всем рекурсивным уровням дерева, вы можете использовать функции prewalk или postwalk clojure.walk в сочетании с вашей собственной функцией:

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

Ответ 2

Функции ходьбы хороши для замены.

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

Передача векторов позволяет вам гарантировать, что вы не просто замените все "X".