我有一组对象
(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定义相等性,并且可以将元素直接添加到Set中。在Clojure中这样做的惯用方法是什么?
答案 0 :(得分:2)
如果要进行此类更新,则应具有关联结构。但是你可以将这个集合变为一个然后再变回:
(-> (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
更新第一条记录,然后将其重新组合成一组。
答案 1 :(得分:0)
假设您使用的是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}}
答案 2 :(得分:0)
以下Clojure函数,update-if-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)))