clojure - Vector Of Maps From Lists


Keywords:clojure 


Question: 

How would I get the following:

[{:foo "a" :bar "b" :biz "c"}
 {:foo "d" :bar "e" :biz "f"}
 {:foo "h" :bar "i" :biz "j"}]

from

("a" "d" "h")
("b" "e" "i")
("c" "f" "j")

Thanks in advance!


3 Answers: 

You can transpose the input using map and zipmap to create the result maps:

(def input ['("a" "d" "h")
            '("b" "e" "i")
            '("c" "f" "j")])

(mapv #(zipmap [:foo :bar :biz] %) (apply map vector input))
 

this is very alike the @lee's variant, but does it in one pass, employing the clojure map's ability to operate on multiple collections:

(def input ['("a" "d" "h")
            '("b" "e" "i")
            '("c" "f" "j")])

(apply mapv #(zipmap [:foo :bar :biz] %&) input)
;;=> [{:foo "a", :bar "b", :biz "c"} 
;;    {:foo "d", :bar "e", :biz "f"} 
;;    {:foo "h", :bar "i", :biz "j"}]
 

map can take operate on multiple sequences. When given multiple sequences, it will take elements from each and call your function with them like so:

(let [s1 '("a" "d" "h")
      s2 '("b" "e" "i")
      s3 '("c" "f" "j")]
  (map (fn [x y z]
         {:foo x :bar y :baz z})
       s1 s2 s3))
;; =>
({:foo "a", :bar "b", :baz "c"}
 {:foo "d", :bar "e", :baz "f"}
 {:foo "h", :bar "i", :baz "j"})