2012-05-16 18 views
10

Devo estrarre una chiave da una mappa usando un valore. C'è un modo per farlo se non implementare la ricerca inversa da solo?ricerca inversa in una mappa

+3

Cosa ho f 2 o più chiavi hanno lo stesso valore? Ne hai bisogno solo uno o tutti? – ivant

risposta

3

Prova

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

È possibile invertire una mappa molto facilmente con una funzione 2-line:

(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: per tutti gli scopi intensivi, ciò che la mappa '{: a 1: b 1}' diventa non è definito. – Jeremy

+0

@Jeremy: non è strettamente indefinito, si otterrà in modo affidabile una ricerca inversa di '{1: a}' o '{1: b}' (quale si ottiene dipende dall'ordinamento interno dell'hashmap). Ma sono d'accordo sul fatto che se hai valori duplicati, probabilmente vuoi dare a questo un trattamento speciale. – mikera

+0

Sì. Intendevo solo che non si poteva fare affidamento. Inoltre, le mappe di piccole dimensioni che sono PersistentArrayMaps possono avere un comportamento * prevedibile * (non necessariamente previsto) fino a quando non vengono forzate in PersistentHashMap. Ma ancora una volta, non è qualcosa su cui ci si dovrebbe basare. – Jeremy

0

Un altro:

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

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

Credo che map-invert è il diritto modo per farlo.

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

Se si utilizza ClojureScript o avete bisogno di un altro alternativa :)

(zipmap (vals m) (keys m))

0

se si desidera mantenere le chiavi, è meglio invertire solo la mappa , ma colleziona le vecchie chiavi in ​​un set/elenco ecc ...

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