Reputation: 93
I have a vector of maps. Each map has three keys :x, :y and :z. I want that the value of :z would be the sum of the values of keys :x and :y. How should I do this? i.e.
[{x: 5 :y 10 :z (+ :x :y)} {...} {...}]
In the above example, the first map's :z value should then be (+ 5 10) = 15.
Thanks for helping!
Upvotes: 0
Views: 259
Reputation: 2792
It may help to parameterize this logic by extracting it out into a function if you plan on repeatedly doing this, although I would just create the :z
key at the time you create the map, since you will presumably have access to x
and y
at that time.
Barring that, here is an alterative to the fine solutions presented already, just generalized for different arguments.
(def ms [{:x 5 :y 10} {:x 5 :y 12} {:x 8 :y 10}])
(defn assoc-from-existing [m k & ks]
(assoc m k (->> (select-keys m ks) vals (apply +))))
(mapv #(assoc-from-existing % :z :x :y) ms)
Upvotes: 0
Reputation: 3528
map
and for
will return a lazy sequence and mapv
will return a vector.A simple solution:
;; first we define the data
(def ms [{x: 5 :y 10} {:x 1 :y 1} {:x 2 :y 3}])
;; then we define a function that creates mutated data
(defn add-sum [ms] (mapv (fn [m] (assoc m :z (+ (:x m) (:y m)))) ms))
Alternatively with for
macro:
(defn add-sum [ms] (for [m ms] (assoc m :z (+ (:x m) (:y m)))))
Or with destructuring:
(defn add-sum [ms] (for [{:keys [x y]} ms] (assoc m :z (+ x y))))
Upvotes: 0
Reputation: 37008
If you want to add those keys afterwards, you have to look at how to manipulate maps. In this case e.g. Destructuring and assoc
are fine:
user=> (def m {:x 42 :y 666})
#'user/m
user=> (let [{:keys [x y]} m] (assoc m :z (+ x y)))
{:x 42, :y 666, :z 708}
Or if you want to create new maps with just the coords write a function for that
user=> (defn coord [x y] {:x x :y y :z (+ x y)})
#'user/coord
user=> (coord 42 666)
{:x 42, :y 666, :z 708}
Upvotes: 1