2012-03-11 2 views
1

У меня есть набор объектовКак получить измененный набор после обновления элемента для определенного ключа?

(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

Что вы подразумеваете под "Given key"? В вашем примере у вас есть набор, содержащий три карты. В вашем желаемом примере использования вы передаете набор и новую карту ... но на самом деле это не ключ. Вы хотите обновить карту с помощью:: isbn' из 1? – djhworld

+0

Отредактировано для обновления: isbn – Sathish

+0

Мне интересно, может ли структура данных быть улучшена, чтобы отразить это: isbn должен быть уникальным. –

ответ

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

Если вы хотите сделать что-то обновление, вы должны иметь ассоциативную структуру. Но вы можете превратить набор в одну, а затем снова:

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

Этот код предполагает: ISBN должен быть уникальным (так как вы сказали, «ключ»). Он превращает набор в карту из значений: isbn в последовательности соответствующих записей, обновляет первую запись с помощью :isbn 1 с автором, а затем возвращает ее обратно в набор.

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))) 
Смежные вопросы