更改存储在原子化地图中的矢量的惯用方法是什么?

What is the idiomatic way to alter a vector that is stored in an atomized map?

我有一个名为 app-state 的原子,它包含一张地图。它看起来像这样:

{:skills [{:id 1 :text "hi"} {:id 2 :text "yeah"}]}

使用 :id = 2 删除向量中元素的惯用方法是什么?结果如下:

{:skills [{:id 1 :text "hi"}]}

... 到目前为止,我有这个:

(defn new-list [id]
   (remove #(= id (:id %)) (get @app-state :skills)))

swap! app-state assoc :skills (new-list 2)

它有效,但我觉得这不太正确。我认为它可能是这样的:

swap! app-state update-in [:skills] remove #(= id (:id %))

但这似乎不起作用。

非常感谢任何帮助!

(def skills {:skills [{:id 1 :text "hi"} {:id 2 :text "yeah"}]})

(defn remove-skill [id]
  (update skills :skills (fn [sks] (vec (remove #(= id (:id %)) sks)))))

然后你可以调用 say (remove-skill 1) 并看到只剩下另一个(:id 为 2 的技能)。

我更喜欢你的方式。这需要进行调整才能用于原子。

您可以使用 filter 来执行此操作。这是一个带有 id 和地图的函数,让你过滤掉任何不符合你的标准的东西。当然,您可以根据需要使 #() reader 宏检查是否相等而不是不相等。

user=> (def foo {:skills [{:id 1 :text "hi"} {:id 2 :text "yeah"}]})
#'user/foo
user=> (defn bar [id sklz] (filter #(not= (:id %) id) (:skills sklz)))
#'user/bar
user=> (bar 1 foo)
({:id 2, :text "yeah"})
user=> (bar 2 foo)
({:id 1, :text "hi"})

试试这个:

(defn new-list [app-state-map id]
      (assoc app-state-map :skills (into [] (remove #(= id (:id %)) (:skills app-state-map)))))

(swap! app-state new-list 2)

swap! 会将原子的当前值传递给您提供的函数。没有必要在函数中自己取消引用它。

有关详细信息,请参阅 swap! 上的 docs

(swap! state update :skills (partial remove (comp #{2} :id)))