2015-04-14 21 views
6

Questa è davvero una variazione su questo argomento, ma non un duplicato:Python inversa/invertire una mappatura (ma con più valori per ogni chiave)

Python reverse/invert a mapping

Dato un dizionario in questo modo:

mydict= { 'a': ['b', 'c'], 'd': ['e', 'f'] }

Come si può invertire questa dict per ottenere:

inv_mydict = { 'b':'a', 'c':'a', 'e':'d', 'f':'d' }

Si noti che i valori si estendono univocamente sotto ciascun tasto.

Nota: ho già avuto la sintassi map = ... e dict = ... Promemoria non usare map e dict come sono funzioni built-in, vedere ottimi commenti e le risposte di seguito :)

+1

'map' è una parola chiave, non utilizzare come nome del dizionario. –

+0

Ho cambiato il testo in dettato come risultato –

+2

@KevinLee, 'dict' è anche una parola chiave :-)) – ForceBru

risposta

10

TL; DR

Usa comprensione dizionario, come questo

>>> my_map = { 'a': ['b', 'c'], 'd': ['e', 'f'] } 
>>> {value: key for key in my_map for value in my_map[key]} 
{'c': 'a', 'f': 'd', 'b': 'a', 'e': 'd'} 

La comprensione dizionario visto sopra è funzionalmente equivalente alla seguente struttura di ciclica che popola un dizionario vuoto

>>> inv_map = {} 
>>> for key in my_map: 
...  for value in my_map[key]: 
...   inv_map[value] = key 
... 
>>> inv_map 
{'c': 'a', 'f': 'd', 'b': 'a', 'e': 'd'} 

Nota: Uso map ombre incorporata map funzione. Quindi, non usare questo come nome di variabile a meno che tu non sappia cosa stai facendo.


Altri modi simili a fare lo stesso

Python 3.x

È possibile utilizzare dict.items, come questo

>>> {value: key for key, values in my_map.items() for value in values} 
{'c': 'a', 'f': 'd', 'b': 'a', 'e': 'd'} 

Usiamo items() metodo qui, che creerebbe un oggetto vista dal dizionario wh ich darebbe coppie di valori chiave sull'iterazione. Quindi lo ripetiamo e costruiamo un nuovo dizionario con la mappatura inversa.

Python 2.x

È possibile utilizzare dict.iteritems come questo

>>> {value: key for key, values in my_map.iteritems() for value in values} 
{'c': 'a', 'b': 'a', 'e': 'd', 'f': 'd'} 

Non preferiamo items() metodo 2.x, perché restituirà un elenco di coppie chiave-valore . Non vogliamo costruire una lista solo per iterare e costruire un nuovo dizionario. Questo è il motivo per cui preferiamo iteritems(), che restituisce un oggetto iteratore che fornisce una coppia di valori chiave su iterazione.

Nota: L'equivalente attuale di Python 3.x items sarebbe il metodo di Python 2.x viewitems, che restituisce un oggetto vista. Maggiori informazioni sull'oggetto della vista nella documentazione ufficiale, here.


iter* vs view* metodi in Python 2.x

La differenza principale tra iter* funzioni e view* funzioni in Python 2.x è che, sottofinestre riflettono lo stato attuale del dizionario. Ad esempio,

>>> d = {1: 2} 
>>> iter_items = d.iteritems() 
>>> view_items = d.viewitems() 

Ora si aggiunge un nuovo elemento al dizionario

>>> d[2] = 3 

Se si tenta di controllare se (2, 3) (coppia chiave-valore) è in iter_items, verrà generato un errore

>>> (2, 3) in iter_items 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
RuntimeError: dictionary changed size during iteration 

ma l'oggetto vista rifletterà lo stato corrente del dizionario. Così, funzionerà bene

>>> (2, 3) in view_items 
True 
2
mp = { 'a': ['b', 'c'], 'd': ['e', 'f'] } 

pm={} 
for x in mp.iterkeys(): 
    for d in mp[x]: 
     pm[d]=x 

print pm 

uscita:

{ 'c': 'a', 'b': 'a', 'e': 'd', ' f ': 'd'}

Nota: un dizionario è una struttura dati unordored, in modo che il risultato non può essere ordinato come si vuole che sia.

+0

Grazie per il promemoria non ordinato, ho finito per usare la libreria 'natsort' per ordinare il mio dizionario. –