Obtener clave por valor en el diccionario
Hice una función que buscará edades en a Dictionary
y mostrará el nombre coincidente:
dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
for age in dictionary.values():
if age == search_age:
name = dictionary[age]
print name
Sé comparar y encontrar la edad, pero no sé cómo mostrar el nombre de la persona. Además, recibo un error KeyError
debido a la línea 5. Sé que no es correcto, pero no sé cómo hacer que busque hacia atrás.
mydict = {'george': 16, 'amber': 19}
print mydict.keys()[mydict.values().index(16)] # Prints george
O en Python 3.x:
mydict = {'george': 16, 'amber': 19}
print(list(mydict.keys())[list(mydict.values()).index(16)]) # Prints george
Básicamente, separa los valores del diccionario en una lista, encuentra la posición del valor que tiene y obtiene la clave en esa posición.
Más sobre keys()
y .values()
en Python 3: ¿Cómo puedo obtener una lista de valores de dict?
No hay ninguno. dict
no está diseñado para usarse de esta manera.
dictionary = {'george': 16, 'amber': 19}
search_age = input("Provide age")
for name, age in dictionary.items(): # for name, age in dictionary.iteritems(): (for Python 2.x)
if age == search_age:
print(name)
Si quieres tanto el nombre como la edad, deberías usar .items()
la que te proporciona las tuplas clave (key, value)
:
for name, age in mydict.items():
if age == search_age:
print name
Puede descomprimir la tupla en dos variables separadas directamente en el for
bucle y luego hacer coincidir la edad.
También deberías considerar invertir el diccionario si generalmente vas a buscar por edad y no hay dos personas que tengan la misma edad:
{16: 'george', 19: 'amber'}
para que puedas buscar el nombre de una edad con solo hacer
mydict[search_age]
Lo he estado llamando mydict
en lugar de list
porque list
es el nombre de un tipo integrado y no deberías usar ese nombre para nada más.
Incluso puedes obtener una lista de todas las personas con una edad determinada en una línea:
[name for name, age in mydict.items() if age == search_age]
o si hay una sola persona con cada edad:
next((name for name, age in mydict.items() if age == search_age), None)
que solo te dará None
si no hay nadie con esa edad.
Finalmente, si dict
es largo y estás en Python 2, deberías considerar usarlo .iteritems()
en lugar de .items()
como lo hizo Cat Plus Plus en su respuesta, ya que no es necesario hacer una copia de la lista.
Pensé que sería interesante señalar qué métodos son los más rápidos y en qué escenario:
Aquí hay algunas pruebas que realicé (en una MacBook Pro 2012)
def method1(dict, search_age):
for name, age in dict.iteritems():
if age == search_age:
return name
def method2(dict, search_age):
return [name for name,age in dict.iteritems() if age == search_age]
def method3(dict, search_age):
return dict.keys()[dict.values().index(search_age)]
Resultados de profile.run()
cada método 100.000 veces:
Método 1:
>>> profile.run("for i in range(0,100000): method1(dict, 16)")
200004 function calls in 1.173 seconds
Método 2:
>>> profile.run("for i in range(0,100000): method2(dict, 16)")
200004 function calls in 1.222 seconds
Método 3:
>>> profile.run("for i in range(0,100000): method3(dict, 16)")
400004 function calls in 2.125 seconds
Esto muestra que para un dictado pequeño, el método 1 es el más rápido. Lo más probable es que esto se deba a que devuelve la primera coincidencia, a diferencia de todas las coincidencias como en el método 2 (consulte la nota a continuación).
Curiosamente, al realizar las mismas pruebas en un dict que tengo con 2700 entradas, obtengo resultados bastante diferentes (esta vez lo ejecuto 10,000 veces):
Método 1:
>>> profile.run("for i in range(0,10000): method1(UIC_CRS,'7088380')")
20004 function calls in 2.928 seconds
Método 2:
>>> profile.run("for i in range(0,10000): method2(UIC_CRS,'7088380')")
20004 function calls in 3.872 seconds
Método 3:
>>> profile.run("for i in range(0,10000): method3(UIC_CRS,'7088380')")
40004 function calls in 1.176 seconds
Entonces aquí, el método 3 es mucho más rápido. Solo sirve para mostrar que el tamaño de su dictado afectará el método que elija.
Notas:
- El método 2 devuelve una lista de todos los nombres, mientras que los métodos 1 y 3 devuelven sólo la primera coincidencia.
- No he considerado el uso de memoria. No estoy seguro de si el método 3 crea 2 listas adicionales (
keys()
yvalues()
) y las almacena en la memoria.