Diccionario bidireccional en Python
Este post fue migrado de un blog hecho con Wordpress. Si se ve mal, dejame un comentario y lo arreglo.
Bidirectional dict o Injective mapping es una estructura de datos muy útil.
Por lo general cuando usamos un diccionario o tabla hash, tenemos un valor asociado a una clave:
>>> d = {1:'uno', 2:'dos'}>>> d[1]
'uno'
Pero algunas veces también resulta útil indexar por el valor y obtener la clave.
>>> d['uno']
1
Por ejemplo, en un programa tengo un archivo de configuración que contiene un diccionario dónde las claves son strings de 3 caracteres representando un edificio ('SFE', 'GDP', ...) y las claves números de puerto (5007, 5008, ...). En algunas partes el programa requiere conocer el edificio a partir del número de puerto y en otras el puerto a partir del edificio.
¿Cómo obtenemos este comportamiento?
Pregunté en StackOverflow y si bien me apuntaron a una implementación, la solución que más me gustó fue esta:
>>> d.update( dict((d[k], k) for k in d))
Así se ve d
ahora:
{1: 'uno', 2: 'dos', 'uno': 1, 'dos': 2}
Y podemos efectivamente indexar por clave o por valor:
>>> d[1] 'uno' >>> d['uno'] 1
Advertencias
No se pueden usar objetos mutables
En los diccionarios de Python solo objetos inmutables pueden ser clave de diccionarios, por lo tanto, en nuestro diccionario bidireccional, tanto las claves como los valores deberán serlo.
Actualizaciones
Otra limitación de este enfoque son las desincronizaciones que puede sufrir al modificar el bidict luego de realizar la transformación; hay que tener cuidado!
- Luego de agregar un nuevo elemento debemos volver a ejecutar la línea mágica para que cree la entrada inversa.
- No podemos agregar un par que tenga como clave algo que ya existía como valor o que tenga como valor algo que ya existía como clave.
- Si borramos una entrada, hay que también borrar su inversa.
Conclusión personal
Como les contaba antes, yo estaba usando el diccionario original en un archivo de configuración, por lo que no toco la estructura de datos durante la ejecución del programa, así que esta solución compacta y elegante... como dijo el filósofo: me viene al pelo!
Espero a alguien más le sirva.
Comentarios
Comments powered by Disqus