Reputation: 8183
I have to extract a key from a map using a value. Is there a way to do this other than implementing reverse lookup myself?
Upvotes: 11
Views: 3981
Reputation: 5759
if you want to keep the keys, it is better to just invert the map, but collect the old keys in a set / list etc...
(defn map-inverse [m]
(reduce (fn [m' [k v]] (update m' v clojure.set/union #{k})) {} m))
(defn map-inverse [m]
(reduce (fn [m' [k v]] (update m' v conj k)) {} m))
Upvotes: 0
Reputation: 422
If you are using ClojureScript or you need one more alternative :)
(zipmap (vals m) (keys m))
Upvotes: 2
Reputation: 106381
You can reverse a map really easily with a 2-line function:
(defn reverse-map [m]
(into {} (map (fn [[a b]] [b a]) m)))
(def a {:a 1 :b 2 :c 3})
(reverse-map a)
=> {1 :a, 3 :c, 2 :b}
((reverse-map a) 1)
=> :a
Upvotes: 6
Reputation: 59385
I think that map-invert
is the right way to do this.
;; Despite being in clojure.set, this has nothing to do with sets.
user=> (map-invert {:a 1, :b 2})
{2 :b, 1 :a}
;; If there are duplicate keys, one is chosen:
user=> (map-invert {:a 1, :b 1})
{1 :b}
;; I suspect it'd be unwise to depend on which key survives the clash.
Upvotes: 26
Reputation: 19747
Another one:
(defn reverse-map [m]
(apply hash-map (mapcat reverse m)))
(defn reverse-lookup [m k]
(ffirst (filter (comp #{k} second) m)))
Upvotes: 0