Search code examples
clojureinsert-update

Clojure: Create or update Map values in a vector


I want to update some values in my vector.

To change this :

[{:key 0, :values {:value1 1, :value2 100}} {:key 1, :values {:value1 5, :value2 300}}]

In this:

[{:key 0, :values {:value1 1, :value2 100}} {:key 1, :values {:value1 6, :value2 500}}]

I'm trying to do something like that, without success:

(if (contains? myvectors myId)
  (do
    (assoc ((myvectors myId) :values) :value2 500));not working
  )
  (do
    (def myvectors (merge myvectors {:key myId :values {:value1 1 :value2 300}}))
  )
)

Solution

  • This would work:

    (def v
      [{:key 0 :values {:value1 1 :value2 100}} {:key 1 :values {:value1 5, :value2 300}}])
    
    (defn update-values [v k value1 value2]
      (mapv (fn [{:keys [key] :as m}]
              (cond-> m
                (= key k) (assoc :values {:value1 value1 :value2 value2})))
            v))
    
    (update-values v 1 6 500)
    ;; => [{:key 0 :values {:value1 1 :value2 100}} 
    ;;     {:key 1 :values {:value1 6 :value2 500}}]
    

    If possible I would change your data structure so you can make better use of core functions, for example a map from key to values:

    (def m
      {0 {:value1 1 :value2 100}
       1 {:value1 5 :value2 300}})
    
    (assoc m 1 {:value1 6 :value2  500})
    ;; => {0 {:value1 1 :value2 100}
    ;;     1 {:value1 6 :value2 500}}