Wei Liu
Wei Liu

Reputation: 43

How to build hash map of sets

I think I am struggling with some basics of clojure's immutable hash map.

I want to turn a list of tuples in to a hash-map

([:a 2] [:b 3] [:a 1] [:b 3]) ==> {:a #{2 1}, :b #{3}}

That is, in python I would do:

hash_map = defaultdict(set)

for key, value in my_list:
  hash_map[key].add(value)

How should I do this in clojure?

Upvotes: 0

Views: 141

Answers (3)

Thumbnail
Thumbnail

Reputation: 13473

Slow but sure:

(defn pairs-to-graph [pairs]
  (apply merge-with clojure.set/union 
        (map (fn [[k v]] {k #{v}}) pairs)))

(pairs-to-graph '([:a 2] [:b 3] [:a 1] [:b 3]))
;{:b #{3}, :a #{1 2}}

Upvotes: 0

xsc
xsc

Reputation: 6073

Oh, so many useful Clojure functions to touch:

(reduce
  (fn [m [k v]]
    (update-in m [k] (fnil conj #{}) v))
  {} data)
;; => {:b #{3}, :a #{1 2}}

It's actually quite close to the Python code: you iterate over the seq using reduce, add the value to the map using update-in and conj and make sure the value is initialized with an empty set using fnil.

Upvotes: 2

TheQuickBrownFox
TheQuickBrownFox

Reputation: 10624

(defn pairs-to-hash [pairs]
  (into {}
        (map (fn [kv]
               [(key kv) (->> kv val (map second) set)])
             (group-by first pairs))))

(pairs-to-hash '([:a 2] [:b 3] [:a 1] [:b 3]))

This was a quick attempt that I think could be neatened up a bit.

Upvotes: 0

Related Questions