2012-05-16 14 views
10

Tengo que extraer una clave de un mapa utilizando un valor. ¿Hay alguna manera de hacer esto aparte de implementar la búsqueda inversa?búsqueda inversa en un mapa

+3

Lo que i f 2 o más teclas tienen el mismo valor? ¿Necesitas solo uno de ellos, o todos? – ivant

Respuesta

3

Trate

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

Puede invertir un mapa muy fácilmente con una función de 2 líneas:

(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

Nota: Para todos los propósitos intensivos, lo que el mapa '{: a 1: b 1}' pasa a ser no está definido. – Jeremy

+0

@Jeremy: no está estrictamente indefinido, de manera confiable obtendrá una búsqueda inversa de '{1: a}' o '{1: b}' (la que obtenga depende del orden interno del hashmap). Pero estoy de acuerdo en que si tienes valores duplicados, probablemente quieras darle un tratamiento especial. – mikera

+0

Sí. Lo único que quería decir es que no se debe confiar en eso. Además, los pequeños mapas que son PersistentArrayMaps pueden tener un comportamiento * predecible * (no necesariamente esperado) hasta que se los fuerce en un PersistentHashMap. Pero, de nuevo, no es algo en lo que se deba confiar. – Jeremy

0

Otra:

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

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

Creo que map-invert es el derecho forma de hacer esto.

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

Si está utilizando ClojureScript o necesita una alternativa más :)

(zipmap (vals m) (keys m))

0

si desea guardar las llaves, es mejor simplemente invertir el mapa , pero recoge las llaves antiguas en un conjunto/lista, 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)) 
Cuestiones relacionadas