Clojure get map key by value

As in many other cases you can use for:

(def hm {:foo "bar"})
(for [[k v] hm :when (= v "bar")] k)

And with "some" you can return the first matching item instead of a list (as probably the original question implied):

(some (fn [[k v]] (if (= v "bar") k)) hm)

There can be multiple key/value pairs with value "bar". The values are not hashed for lookup, contrarily to their keys. Depending on what you want to achieve, you can look up the key with a linear algorithm like:

(def hm {:foo "bar"})
(keep #(when (= (val %) "bar")
          (key %)) hm)

Or

(filter (comp #{"bar"} hm) (keys hm))

Or

(reduce-kv (fn [acc k v]
             (if (= v "bar")
               (conj acc k)
               acc))
           #{} hm)

which will return a seq of keys. If you know that your vals are distinct from each other, you can also create a reverse-lookup hash-map with

(clojure.set/map-invert hm)

user> (->> {:a "bar" :b "foo" :c "bar" :d "baz"} ; initial map
           (group-by val)   ; sorted into a new map based on value of each key
           (#(get % "bar")) ; extract the entries that had value "bar"
           (map key))     ; get the keys that had value bar
(:a :c)

Tags:

Clojure