sumar - Python: ¿La mejor manera de intercambiar claves con valores en un diccionario?
recorrer un diccionario en python (16)
Recibo un diccionario como entrada y me gustaría devolver un diccionario cuyas claves serán los valores de entrada y cuyo valor serán las claves de entrada correspondientes. Los valores son únicos.
Por ejemplo, digamos que mi aporte es:
a = dict()
a[''one'']=1
a[''two'']=2
Me gustaría que mi salida fuera:
{1: ''one'', 2: ''two''}
Para aclarar, me gustaría que mi resultado fuera el equivalente a lo siguiente:
res = dict()
res[1] = ''one''
res[2] = ''two''
¿Alguna forma ordenada de Pythonian para lograr esto?
Gracias
Añadiendo una solución en el lugar:
>>> d = {1: ''one'', 2: ''two'', 3: ''three'', 4: ''four''}
>>> for k in list(d.keys()):
... d[d.pop(k)] = k
...
>>> d
{''two'': 2, ''one'': 1, ''four'': 4, ''three'': 3}
En Python3, es fundamental que use list(d.keys())
porque dict.keys
devuelve una vista de las claves. Si está utilizando Python2, d.keys()
es suficiente.
Desde Python 2.7 en adelante, incluyendo 3.0+, hay una versión posiblemente más corta y más legible:
>>> my_dict = {''x'':1, ''y'':2, ''z'':3}
>>> {v: k for k, v in my_dict.items()}
{1: ''x'', 2: ''y'', 3: ''z''}
La respuesta principal actual asume que los valores son únicos, lo que no siempre es así. ¿Qué pasa si los valores no son únicos? ¡Perderás información! Por ejemplo:
d = {''a'':3, ''b'': 2, ''c'': 2}
{v:k for k,v in d.iteritems()}
devuelve {2: ''b'', 3: ''a''}
.
La información sobre ''c''
fue completamente ignorada. Idealmente, debería haber sido algo como {2: [''b'',''c''], 3: [''a'']}
. Esto es lo que hace la implementación inferior.
def reverse_non_unique_mapping(d):
dinv = {}
for k, v in d.iteritems():
if v in dinv:
dinv[v].append(k)
else:
dinv[v] = [k]
return dinv
Otra forma de ampliar la respuesta de Ilya Prokin es utilizar la función reversed
.
dict(map(reversed, my_dict.items()))
En esencia, su diccionario se itera a través de (usando .items()
) donde cada elemento es un par clave / valor, y esos elementos se intercambian con la función reversed
. Cuando esto se pasa al constructor de dict
, los convierte en pares de valor / clave, que es lo que desea.
Puedes hacer uso de dictados :
res = {v: k for k, v in a.iteritems()}
Editado: para Python 3, use a.items()
lugar de a.iteritems()
. Las discusiones sobre las diferencias entre ellos se pueden encontrar en los iteritems en Python en SO.
Python 2:
res = dict((v,k) for k,v in a.iteritems())
Python 3 (gracias a @erik):
res = dict((v,k) for k,v in a.items())
Se puede hacer fácilmente con la comprensión del diccionario:
{d[i]:i for i in d}
Si estás usando Python3, es ligeramente diferente:
res = dict((v,k) for k,v in a.items())
Sugerencia para mejorar la respuesta de Javier:
dict(zip(d.values(),d))
En lugar de d.keys()
puede escribir solo d
, porque si pasa por un diccionario con un iterador, devolverá las claves del diccionario correspondiente.
Ex. para este comportamiento:
d = {''a'':1,''b'':2}
for k in d:
k
''a''
''b''
Tu podrías intentar:
d={''one'':1,''two'':2}
d2=dict((value,key) for key,value in d.iteritems())
d2
{''two'': 2, ''one'': 1}
Tenga en cuenta que no puede "revertir" un diccionario si
- Más de una clave comparte el mismo valor. Por ejemplo,
{''one'':1,''two'':1}
. El nuevo diccionario solo puede tener un elemento con la tecla1
. - Uno o más de los valores son inestables. Por ejemplo,
{''one'':[1]}
.[1]
es un valor válido pero no una clave válida.
Vea este hilo en la lista de correo de python para una discusión sobre el tema.
Utilizando bucle : -
newdict = {} #Will contain reversed key:value pairs.
for key, value in zip(my_dict.keys(), my_dict.values()):
# Operations on key/value can also be performed.
newdict[value] = key
res = dict(zip(a.values(), a.keys()))
dict(map(lambda x: x[::-1], YourDict.items()))
.items()
devuelve una lista de tuplas de (key, value)
. map()
recorre los elementos de la lista y aplica lambda x:[::-1]
a cada uno de sus elementos (tupla) para revertirla, por lo que cada tupla se convierte (value, key)
en la nueva lista que se saca del mapa. Finalmente, dict()
hace un dict de la nueva lista.
new_dict = dict (zip(my_dict.values(),my_dict.keys()))
new_dict = dict( (my_dict[k], k) for k in my_dict)
O incluso mejor, pero solo funciona en Python 3:
new_dict = { my_dict[k]: k for k in my_dict}
In [1]: my_dict = {''x'':1, ''y'':2, ''z'':3}
In [2]: dict((value, key) for key, value in my_dict.iteritems())
Out[2]: {1: ''x'', 2: ''y'', 3: ''z''}