Clojure 更新特定键的元素后,如何获得修改集?

Clojure 更新特定键的元素后,如何获得修改集?,clojure,Clojure,我有一套物品 (def books #{{:isbn 1 :title "Programming Clojure"} {:isbn 2 :title "Joy of Clojure"} {:isbn 3 :title "Clojure in Action"}}) 如何更新具有给定键(:isbn)的对象并返回修改的集 (??? books :isbn {:isbn 1 :title "Programming Clojure" :author "

我有一套物品

(def books #{{:isbn 1 :title "Programming Clojure"}
             {:isbn 2 :title "Joy of Clojure"}
             {:isbn 3 :title "Clojure in Action"}})
如何更新具有给定键(:isbn)的对象并返回修改的集

(??? books :isbn {:isbn 1 :title "Programming Clojure" :author "Halloway"})

在Java中,可以使用isbn定义相等,元素可以直接添加到集合中。Clojure的惯用方法是什么?

假设您使用ISBN号作为“键”,下面是我的解决方案

(defn update-set [coll k new-map]
   (reduce (fn [new-set existing-map] 
             (if (= (k existing-map) (k new-map)) 
               (conj new-set new-map) 
               (conj new-set existing-map))) #{} coll)) 

(update-set books :isbn {:isbn 1 :title "Programming Clojure" :author "Halloway"})
; => #{{:title "Joy of Clojure", :isbn 2} {:author "Halloway", :title "Programming Clojure",   :isbn 1} {:title  "Clojure in Action", :isbn 3}}

如果要进行此类更新,则应具有关联结构。但您可以将集合转换为一个,然后再返回:

(-> (group-by :isbn books)
    (assoc-in [1 0 :author] "Halloway") ; 1 is the isbn, 0 means "first"
    vals 
    (->> (map first)) 
    set)

此代码假定:isbn是唯一的(因为您说的是“key”)。它将集合转换为一个从:isbn值到相应记录序列的映射,用作者的
:isbn 1
更新第一条记录,然后将其重新组合成一个集合。

以下Clojure函数(如果isbn是非公共函数,则更新)将解决您的问题

(defn- update-if-isbn [isbn k v book] 
  (if (= (:isbn book) isbn) (assoc book k v) book))

(defn update-books [isbn k v books] 
  (set (map (partial update-if-isbn isbn k v) books)))

你说的“给钥匙”是什么意思?根据您的示例,您有一个包含三个贴图的集合。在您想要的使用示例中,您正在传递集合和一个新映射……但这并不是一个真正的键。是否要使用1的
:isbn
更新地图?我想知道是否可以改进数据结构以反映:isbn应该是唯一的。