Encontrar la clave de valor en el diccionario de Python:

Bastante nuevo en Python, todavía luchando con tanta información.

Toda la documentación que he visto sobre diccionarios explica varias formas de obtener un valor a través de una clave, pero estoy buscando una forma pythonica de hacer lo contrario: obtener una clave a través de un valor.

Sé que puedo recorrer las claves e inspeccionar sus valores hasta que encuentre el valor que estoy buscando y luego tome la clave, pero estoy buscando una ruta directa.

No hay ruta directa. Sin embargo, es bastante fácil con las listas de comprensión;

[k for k, v in d.iteritems() if v == desired_value] 

Si necesita hacer esto de vez en cuando y no cree que valga la pena indexarlo de la otra manera, podría hacer algo como:

 class bidict(dict): def key_with_value(self, value, default=None): for k, v in self.iteritems(): if v == value: return v return default def keys_with_value(self, value, default=None): return [v for k, v in self.iteritems() if v == value] 

Entonces d.key_with_value se comportaría como d.get , excepto al revés.

También puedes hacer una clase que la indexe de forma automática. La clave y el valor tendrían que ser hashable, entonces. Aquí hay tres formas en que podría implementarse:

  • En dos dictados separados, con la exposición de algunos métodos similares a dict; quizás podrías hacer foo.by_key[key] o foo.by_value[value] . (No se ha dado ningún código, ya que es más complicado y soy perezoso y creo que esto no es óptimo).

  • En una estructura diferente, para que puedas hacer d[key] d.inverse[value] :

     class bidict(dict): def __init__(self, *args, **kwargs): self.inverse = {} super(bidict, self).__init__(key, value) def __setitem__(self, key, value): super(bidict, self).__setitem__(key, value) self.inverse[value] = key def __delitem__(self, key): del self.inverse[self[key]] super(bidict, self).__delitem__(key) 
  • En la misma estructura, para que puedas hacer d[key] d[value] :

     class bidict(dict): def __setitem__(self, key, value): super(bidict, self).__setitem__(key, value) super(bidict, self).__setitem__(value, key) def __delitem__(self, key): super(bidict, self).__delitem__(self[key]) super(bidict, self).__delitem__(key) 

(En particular, ausente de estas implementaciones de un bidict es el método de update que será un poco más complejo (pero la help(dict.update) indicará lo que necesitaría cubrir). Sin update , el bidict({1:2}) no No haga lo que estaba destinado a hacerlo, ni d.update({1:2}) .

También considere si alguna otra estructura de datos sería más apropiada.

Como su diccionario puede contener valores duplicados (es decir, {'a': 'A', 'b': 'A'} ), la única forma de encontrar una clave a partir de un valor es iterar sobre el diccionario como lo describe.

O … construir el diccionario opuesto. Tienes que recrearlo después de cada modificación del diccionario original.

O … escribe una clase que mantenga el diccionario de ambos sentidos. Tendrá que gestionar situaciones donde aparezca un valor duplicado.

La primera solución con la lista de comprensión es buena. pero una pequeña solución para Python 3.x, en lugar de .iteritems() debería ser solo .items() :

 [k for k, v in d.items() if v == desired_value] 

La construcción de un diccionario opuesto no es del todo buena, ya que una o más claves tienen el mismo valor, pero si lo invierte, debe insertar la clave: [value1, …] estructura que lo llevará a otro problema.