Clojure。更新双重嵌套值

aar*_*rio 1 clojure clojurescript

我是 Clojure 的新手,一切都很新,但也很有趣。所以我有这个数据:

 {:test {:title "Some Title"}, :questions [
   {:id 1, :full-question {:question "Foo question", :id 1, :answers [{:id 7, :question_id 1, :answer "Foobar answer"}, {:id 8, :question_id 1, :answer "Foobar answer two"}]}},
   {:id 5, :full-question {:question "Foo question", :id 5, :answers [{:id 12, :question_id 5, :answer "Foobar answer"}]}},
   {:id 9, :full-question {:question "Foo question", :id 9, :answers [{:id 14, :question_id 9, :answer "Foobar answer"}, {:id 20, :question_id 9, :answer "Foobar answer two"}]}}
 ]}
Run Code Online (Sandbox Code Playgroud)

“经典”测试->问题->回答类型的数据结构。我有这个新信息:

 (def new-answer {:id 33, :answer "Another foobar answer", :question-id 9 })
Run Code Online (Sandbox Code Playgroud)

我需要更新第一个结构以将“新答案”添加到:questions向量中:id编号 9的“答案”中。

我尝试使用update-in函数,但我不知道在两个向量内的地图中告诉通讯员什么:id。我的意思是,我不知道如何构建我想要进行更改的“路径”。

lee*_*ski 5

此外,还有一个很好的库用于这种结构编辑,称为幽灵

你的情况可以这样解决:

(require '[com.rpl.specter :refer [ALL AFTER-ELEM setval]])

(defn add-answer [data {question-id :question-id :as new-answer}]
  (setval [:questions ALL #(== question-id (:id %)) :full-question :answers AFTER-ELEM]
          new-answer data))

user> (add-answer data {:id 33, :answer "Another foobar answer", :question-id 9 })

;;=> {:test {:title "Some Title"},
;;    :questions
;;    [
;;     ;; ... all other ids
;;     {:id 9,
;;      :full-question
;;      {:question "Foo question",
;;       :id 9,
;;       :answers
;;       [{:id 14, :question_id 9, :answer "Foobar answer"}
;;        {:id 20, :question_id 9, :answer "Foobar answer two"}
;;        {:id 33, :answer "Another foobar answer", :question-id 9}]}}]}
Run Code Online (Sandbox Code Playgroud)