更新Clojure原子的多个元素

更新Clojure原子的多个元素,clojure,Clojure,我有一个原子: (def data (atom[ {:orderid 0 :productid 0 :description "A" :amount 2} {:orderid 1 :productid 1 :description "A" :amount 2}])) 和我的交换功能: (defn edit-order [params] (filter #(and (= (:orderid %) (:orderid params))) @data (s

我有一个原子:

(def data (atom[ {:orderid 0 :productid 0 :description "A" :amount 2}  {:orderid 1 :productid 1 :description "A" :amount 2}]))
和我的交换功能:

 (defn edit-order [params]
  (filter
        #(and (= (:orderid %) (:orderid params)))
        @data
  (swap! data (fn [old new] (merge old new)) params))
我得到的结果是:

(println (edit-order  {:orderid 0 :description "edited" :amount 3})) 
;=> [{:orderid 0, :productid 0, :description A, :amount 2} {:orderid 1, :productid 1, :description A, :amount 2} {:orderid 0, :description edited, :amount 3}]
我试图做的是将新值更新为旧值,而不是将其作为新值添加。我该怎么做

;=> [{:orderid 0, :productid 0, :description edited, :amount 3} {:orderid 1, :productid 1, :description A, :amount 2}]

谢谢你的帮助

解决这个问题的方法是:

(def data (atom
           [{:orderid 0 :productid 0 :description "A" :amount 2}
            {:orderid 1 :productid 1 :description "A" :amount 2}]))

(defn edit-order
  [params]
  (swap! data
         (fn [old-orders]
           (mapv (fn [order]
                   (if (= (:orderid order)
                          (:orderid params))
                     (merge order params)
                     order))
                 old-orders))))

(comment
  (edit-order {:orderid 0 :description "edited" :amount 3})
  #_ [{:orderid 0, :productid 0, :description "edited", :amount 3}
      {:orderid 1, :productid 1, :description "A", :amount 2}]
  )

请注意,不能在向量中仅变异一个贴图。您正在基于旧的向量创建一个全新的向量,因为atom中的整个数据结构(应该)是不可变的。

如果要进行大量嵌套结构操作,另一个选项是使用,在本例中是“transform”操作

(ns specterplay.core
  (:require [com.rpl.specter :refer :all]))

(def data (atom[ {:orderid 0 :productid 0 :description "A" :amount 2}  {:orderid 1 :productid 1 :description "A" :amount 2}]))

(defn edit-order!
  [params data]
  (swap! data
         (fn [a] (transform [ALL #(= (:orderid params) (:orderid %))] #(merge % params) a))))

(edit-order! {:description "edited" :amount 3} data)

@data
;; [{:orderid 0, :productid 0, :description "edited", :amount 3} {:orderid 1, :productid 1, :description "A", :amount 2}]
#(=0(:orderid%)中的0是什么意思?哦,应该是(:orderid参数)。固定的。