如何在Clojure中更新原子的向量元素?

kak*_*ori 4 clojure

我有一个矢量原子,我想更新一个本身就是地图的条目.

(def vector-atom (atom []))
(swap! vector-atom conj { :id 1 :name "myname" })
Run Code Online (Sandbox Code Playgroud)

我将如何仅更新此会员?

在可变的Java领域的思维模式中,我会做这样的事情:

(defn find-by-id [id]
  (first (filter (fn [entry] (= (:id entry) id))
         @vector-atom)))

(defn update-entry [id new-entry]
  (let [curr-entry (find-by-id id)
        merged-entry (merge curr-entry new-entry)]
    ###set the curr-entry to merged-entry###))
Run Code Online (Sandbox Code Playgroud)

Mic*_*zyk 13

如果向量的索引对应于:ids,则可以使用类似的东西

(swap! vector-atom update-in [id] merge new-entry)
Run Code Online (Sandbox Code Playgroud)

如果他们不这样做,那么你有两个选择:(1)使用id - > map而不是vector和上面的简单解决方案,(2)使用一个向量,如下所示:

(swap! vector-atom
       (fn [v]
         (let [i (find-index-of-entry v)]
           (assoc v i (merge (nth v i) new-entry)))))
Run Code Online (Sandbox Code Playgroud)

find-index-of-entry可以是向量的简单线性扫描,或者如果项目按顺序排序:id,则可以是二进制搜索.对于较长的矢量,线性扫描当然是非常低效的(因此,如果矢量可能更长,则根据上述(1)切换到映射是值得考虑的解决方案).