5

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.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
rooftop
  • 3,031
  • 1
  • 22
  • 33
  • 1
    "My OO brain wants me to write a bunch of loops" << Loops are a characteristic of imperative programming, not OOP. The two are orthogonal. – missingfaktor Jul 22 '12 at 07:13

2 Answers2

10

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}]
Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • 1
    Yes! That's exactly what I was looking for and was dancing around the edges of for a while. Thanks! – rooftop Jul 20 '12 at 16:01
1

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.

missingfaktor
  • 90,905
  • 62
  • 285
  • 365