Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure 101 combining vectors into a map

I'm very new to Clojure and can't seem to find a way to do something that I'm sure is trivial. I've looked at the assoc function as I think this might be the answer, but can't make it work.

What I have:

keys => [:num, :name, :age]
people =>  [ [1, "tim", 31] [2, "bob" 33] [3, "joe", 44] ]

What I want to do is create a vector of maps, each map looks like

[ { :num 1, :name "tim", :age 31 } 
  { :num 2, :name "bob", :age 33 } 
  { :num 3, :name "joe", :age 44 } ]

My OO brain wants me to write a bunch of loops, but I know there is a better way I'm just a bit lost in the big API.

like image 463
rooftop Avatar asked Jul 20 '12 15:07

rooftop


2 Answers

Try this:

(def ks [:num :name :age])
(def people [[1 "tim" 31] [2 "bob" 33] [3 "joe" 44]])

(map #(zipmap ks %) people)

=> ({:num 1, :name "tim", :age 31}
    {:num 2, :name "bob", :age 33}
    {:num 3, :name "joe", :age 44})

Notice that I used ks instead of keys for naming the keys, as keys is a built-in procedure in Clojure and it's a bad idea to redefine it. Also be aware that map returns a lazy sequence; if you absolutely need a vector, then do this:

(vec (map #(zipmap ks %) people))

=> [{:num 1, :name "tim", :age 31}
    {:num 2, :name "bob", :age 33}
    {:num 3, :name "joe", :age 44}]
like image 87
Óscar López Avatar answered Oct 17 '22 20:10

Óscar López


A tad bit more elegant, using clojure.core/partial:

(map (partial zipmap keys) people)

And as Óscar suggested, you should use a different name for your keys.

like image 23
missingfaktor Avatar answered Oct 17 '22 19:10

missingfaktor