Convert an array of tuples into a hash-map in Clojure

14,290

Solution 1

user=> (into {} [[:a 1] [:b 2]])
{:a 1, :b 2}

Solution 2

A map is a sequence of MapEntry elements. Each MapEntry is a vector of a key and value. The tuples in the question are already in the form of a MapEntry, which makes things convenient. (That's also why the into solution is a good one.)

user=> (reduce conj {} [[:a 1] [:b 2]])
{:b 2, :a 1}

Solution 3

Assuming that "tupel" means "two-elememt array":

(reduce 
  (fn [m tupel] 
      (assoc m 
            (aget tupel 0) 
            (aget tupel 1))) 
  {} 
  array-of-tupels)

Solution 4

user=> (def a [[:a 4] [:b 6]])
user=> (apply hash-map (flatten a))
{:a 4, :b 6}
Share:
14,290
Mantas Vidutis
Author by

Mantas Vidutis

always on the move. operating a consultancy in SF: turbines.io

Updated on June 05, 2022

Comments

  • Mantas Vidutis
    Mantas Vidutis about 2 years

    I have an array of tuples, where each tuple is a 2 tuple with a key and a value. What would be the cleanest way to convert this array of tuples into a hash-map?

  • Isaac
    Isaac over 13 years
    Nice. If your (to the OP) "array" is in fact a seq, instead of (aget t n) you can use (t n), which is a bit prettier.
  • Michał Marczyk
    Michał Marczyk over 13 years
    Note that this also works for arrays of two-element arrays -- you'd just have to add a (map vec ...) around the array argument: (into {} (map vec an-array-of-two-element-arrays)).
  • Isaac
    Isaac over 13 years
    And again, one of those "duh" moments you so often have while using Clojure. Nice answer.
  • kotarak
    kotarak over 13 years
    (t n) does not work with sequences. It does with vectors. But then you can simply use (into {} array-of-vectors) instead of the reduce.
  • kotarak
    kotarak over 13 years
    But a relatively expensive one.
  • miner49r
    miner49r about 13 years
    flatten is overkill for this problem. You can take advantage of the tuples being in the form of a MapEntry (vector of key and value).
  • Yu Shen
    Yu Shen about 9 years
    Thanks for good explanation! So only vector of 2 elements is MapEntry, thus (into {} [[:a 1] {:b 2}]) will work, but (into {} ['( :a 1 ) {:b 2}]) will not work.It gets the error of "java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.util.Map$Entry". I wonder why can't Clojure treat all 2 elements sequence the same way in this context. It will make it more consistent. What's the reason it does not?
  • Radon Rosborough
    Radon Rosborough almost 8 years
    Never, ever use flatten for a situation like this: it will happily flatten all of your keys and values too, if they happen to be data structures!
  • Dennis Hackethal
    Dennis Hackethal about 4 years
    @MichałMarczyk I don't get it... if you already have an array of arrays, why map vec over them? I think vec just leaves arrays as is...
  • Greyshack
    Greyshack over 3 years
    Why does it have to be vector, why doesnt a list of two element lists work?