3
votes

I have hash-maps and I'm trying to get the intersection between the keys. But the function 'intersection' just work with sets.

So I'm getting the keys, transforming the keys to sets and then calling the intersection, something like this:

(intersection (set (keys map-1)) (set (keys map-2)))

There are a better way to do that?

Thanks

3
That is idiomatic ClojureSymfrog

3 Answers

7
votes

This may be the most straightforward / concise way to do it, and it doesn't require building any sets (which is relatively expensive).

(keys (select-keys map-1 (keys map-2)))

Finally, an optimized version, which is a bit faster, and a bit harder to read:

(keep #(some->> % (find map-1) key) (keys map-2))
2
votes

Your solution is clear and concise.

If performance is a concern, you can avoid constructing the intermediate sets by imitating the structure of clojure.set/intersection:

(defn key-intersection [s1 s2]
  (if (< (count s2) (count s1))
    (recur s2 s1)
    (reduce
     (fn [result item]
       (if (contains? s2 item)
         (conj result item)
         result))
     #{}
     (keys s1))))
1
votes

The following should work for arbitrary numbers of maps

(defn key-intersection [m & ms]
  (reduce #(keys (select-keys %2 %1)) (keys m) ms))

or

(defn key-intersection [m & ms]
  (reduce (fn [v c] (keep #(some->> % (find c) key) v)) (keys m) ms))