Search code examples
clojuremultimap

Converting a sequence of maps into a multimap


I have a sequence of maps.

;; input
[{:country "MX", :video 12345, :customer "cid1"}
 {:country "US", :video 12345, :customer "cid2"}
 {:country "MX", :video 54321, :customer "cid1"}]

I want to convert it into a multimap. I want to generate.

;; output
{"cid1"
     {:actions
          [{:country "MX", :video 12345, :customer "cid1"}
           {:country "MX", :video 12345, :customer "cid1"}]},
 "cid2" 
     {:actions
          [{:country "US", :video 12345, :customer "cid2"}]}}

I feel like I should be using update-in. Something along the lines of... I just have not worked out exactly what some-fn-here looks like and I figured that others may have the same question.

(defn add-mm-entry
    [m e]
    (update-in m [(:customer e)] some-fn-here))

(def output (reduce add-mm-entry {} input))

Figured I'd throw it out to the community while I work on it. If I'm going down the wrong path here let me know.


Solution

  • If I understand the intent correctly, you are grouping by :customer and then wrapping the vector of actions into :actions. You can do the grouping with clojure.core/group-by and then map (clojure.core/map) the result:

    (def v [{:country "MX", :video 12345, :customer "cid1"}
            {:country "US", :video 12345, :customer "cid2"}
            {:country "MX", :video 54321, :customer "cid1"}])
    
    (->> v
         (group-by :customer)
         (map (fn [[cid xs]] {cid {:actions xs}}))
         (into {}))