Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use `zipmap` and when `map vector`?

Tags:

I was asking about the peculiarity of zipmap construct to only discover that I was apparently doing it wrong. So I learned about (map vector v u) in the process. But prior to this case I had used zipmap to do (map vector ...)'s work. Did it work then because the resultant map was small enough to be sorted out?

And to the actual question: what use zipmap has, and how/when to use it. And when to use (map vector ...)?

My original problem required the original order, so mapping anything wouldn't be a good idea. But basically -- apart from the order of the resulting pairs -- these two methods are equivalent, because the seq'd map becomes a sequence of vectors.

(for [pair (map vector v (rest v))]   ( ... )) ;do with (first pair) and (last pair)  (for [pair (zipmap v (rest v))]  ( ... )) ;do with (first pair) and (last pair) 
like image 995
mike3996 Avatar asked May 26 '11 08:05

mike3996


2 Answers

Use (zipmap ...) when you want to directly construct a hashmap from separate sequences of keys and values. The output is a hashmap:

(zipmap [:k1 :k2 :k3] [10 20 40]) => {:k3 40, :k2 20, :k1 10} 

Use (map vector ...) when you are trying to merge multiple sequences. The output is a lazy sequence of vectors:

(map vector [1 2 3] [4 5 6] [7 8 9]) => ([1 4 7] [2 5 8] [3 6 9]) 

Some extra notes to consider:

  • Zipmap only works on two input sequences (keys + values) whereas map vector can work on any number of input sequences. If your input sequences are not key value pairs then it's probably a good hint that you should be using map vector rather than zipmap
  • zipmap will be more efficient and simpler than doing map vector and then subsequently creating a hashmap from the key/value pairs - e.g. (into {} (map vector [:k1 :k2 :k3] [10 20 40])) is quite a convoluted way to do zipmap
  • map vector is lazy - so it brings a bit of extra overhead but is very useful in circumstances where you actually need laziness (e.g. when dealing with infinite sequences)
  • You can do (seq (zipmap ....)) to get a sequence of key-value pairs rather like (map vector ...), however be aware that this may re-order the sequence of key-value pairs (since the intermediate hashmap is unordered)
like image 109
mikera Avatar answered Sep 22 '22 18:09

mikera


The methods are more or less equivalent. When you use zipmap you get a map with key/value pairs. When you iterate over this map you get [key value] vectors. The order of the map is however not defined. With the 'map' construct in your first method you create a list of vectors with two elements. The order is defined.

Zipmap might be a bit less efficient in your example. I would stick with the 'map'.

Edit: Oh, and zipmap isn't lazy. So another reason not to use it in your example.

Edit 2: use zipmap when you really need a map, for example for fast random key-based access.

like image 40
Maurits Rijk Avatar answered Sep 22 '22 18:09

Maurits Rijk