Home > Software engineering >  Clojure - storing maps into a list of maps on keys
Clojure - storing maps into a list of maps on keys

Time:02-19

Say I have two maps in clojure.

(def map1 {:a 1 :b 1 :c nil :d 1})
(def map2 {:a 1 :b 2 :c 3 :d nil})

listofmaps '({:a 1 :b 1 :c nil :d 1} {:a 2 :b 2 :c 2 :d nil})

If :a value matches with any map in listofmaps and map1, then if map1 :d is not null, put :d value from map1 into the matching map in listofmaps.

Like, first we compare map1 and listofmaps - now if map1 (:a 1) matches with any maps in listofmaps (:a 1), if map1 (:d not null) replace (matching map in listofmaps with map1 :d value) and if map1 (:c not null) replace (matching map in listofmaps with map1 :c value)

    map1 {:a 1 :b 1 :c nil :d 1}
    listofmaps '({:a 1 :b 1 :c nil :d 1} {:a 2 :b 2 :c 2 :d nil})

Then map2 (:a 1) matches with a map in listofmaps (:a 1) and :

    map2 {:a 1 :b 2 :c 3 :d nil}
    listofmaps '({:a 1 :b 1 :c nil :d 1} {:a 2 :b 2 :c 2 :d nil})

if map2 (:d not null) replace (matching map in listofmaps with map2 :d value) and if map2 (:c not null) replace (matching map in listofmaps with map2 :c value)

     output=> '({:a 1 :b 1 :c 3 :d 1} {:a 2 :b 2 :c 2 :d nil})

CodePudding user response:

it's not clear what is meant by in list of maps and map2, here is a reasonably common pattern of adding in missing values in priority order.

(let [map1 {:a 1 :b 1 :c nil :d 1}
      map2 {:a 1 :b 2 :c 3 :d nil}
      list-of-maps [{:a 1 :b 1 :c nil :d 1} {:a 2 :b 2 :c 2 :d nil}]
      or-fn (fn [a b] (or a b))] 
 (->>
   list-of-maps
   (map #(merge-with or-fn % map1))
   (map #(merge-with or-fn % map2))))
({:a 1, :b 1, :c 3, :d 1} {:a 2, :b 2, :c 2, :d 1})

CodePudding user response:

I understood your question to be

If the value of the :a key in the map matches the value of the :a key in any map in listofmaps, then, for the keys :c and :d, replace the values in that particular map in listofmaps by a new value only if the new value is not null.

Assuming that, here is an answer. If I did not understand the question correctly, please clarify and show your desired output.

user> (def map1 {:a 1 :b 1 :c nil :d 1})
#'user/map1
user> (def map2 {:a 1 :b 2 :c 3 :d nil})
#'user/map2
user> (def listofmaps [{:a 1 :b 1 :c nil :d 1} {:a 2 :b 2 :c 2 :d nil}])
#'user/listofmaps
user> (defn mapper [m ms]
        (mapv (fn [elem]
                (if (= (:a elem) (:a m))
                  (merge-with #(or %1 %2) (select-keys m [:c :d]) elem)
                  elem))
              maps))
#'user/mapper
user> (mapper map1 listofmaps)
[{:c nil, :d 1, :a 1, :b 1} {:a 2, :b 2, :c 2, :d nil}]
user> (mapper map2 listofmaps)
[{:c 3, :d 1, :a 1, :b 1} {:a 2, :b 2, :c 2, :d nil}]
user> 
  • Related