2012-05-16 43 views
10

我必须使用值从地图中提取密钥。有没有办法做到这一点,而不是自己实施反向查找?在地图中进行反向查找

+3

什么我f 2或更多的键具有相同的值?你只需要其中一个,还是全部? – ivant

回答

3

尝试

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

你真的可以很容易地逆转地图2线功能:

(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 
+1

注意:对于所有密集目的,映射'{:a 1:b 1}'变成的地图是未定义的。 – Jeremy

+0

@Jeremy:它不是严格未定义的,你可以可靠地得到“{1:a}”或“{1:b}”的反向查找(你得到哪一个取决于散列表的内部排序)。但我同意,如果你有重复的价值,你可能想给这个特殊的待遇。 – mikera

+0

是的。我的意思是,它不应该被依赖。此外,PersistentArrayMaps的小图可以具有*可预测的*(不一定是预期的)行为,直到它们被强制为PersistentHashMap。但同样,这不是应该依赖的东西。 – Jeremy

0

还有一句:

(defn reverse-map [m]                               
    (apply hash-map (mapcat reverse m))) 

(defn reverse-lookup [m k]                              
    (ffirst (filter (comp #{k} second) m))) 
25

我认为map-invert是正确的这样做的方法。

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. 
1

如果您正在使用ClojureScript或者你需要一个比较另类的:)

(zipmap (vals m) (keys m))

0
如果你想保持键

,最好是刚刚反转地图,但收集一套/列表等旧密钥...

(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))