Isuru
Isuru

Reputation: 8183

reverse lookup in a map

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

Answers (6)

beoliver
beoliver

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

Bahadir Cambel
Bahadir Cambel

Reputation: 422

If you are using ClojureScript or you need one more alternative :)

(zipmap (vals m) (keys m))

Upvotes: 2

mikera
mikera

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

Eric Wilson
Eric Wilson

Reputation: 59385

I think that map-invert is the right way to do this.

From the docs:

;; 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

Jürgen Hötzel
Jürgen Hötzel

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

jbear
jbear

Reputation: 363

Try

(some #(if (= (val %) your-val) (key %)) your-map) 

Upvotes: 3

Related Questions