python ordereddict to dict
Python: defaultdict of defaultdict? (4)
¿Hay alguna manera de tener un código defaultdict(defaultdict(int))
para que funcione el siguiente código?
for x in stuff:
d[x.a][x.b] += x.c_int
d
necesita ser construido ad-hoc, dependiendo de los elementos xa
y xb
.
Podría usar:
for x in stuff:
d[x.a,x.b] += x.c_int
pero entonces no podría usar:
d.keys()
d[x.a].keys()
El parámetro para el constructor defaultdict es la función que se llamará para construir nuevos elementos. Así que vamos a usar una lambda!
>>> from collections import defaultdict
>>> d = defaultdict(lambda : defaultdict(int))
>>> print d[0]
defaultdict(<type ''int''>, {})
>>> print d[0]["x"]
0
Desde Python 2.7, hay una solución aún mejor con Counter :
>>> from collections import Counter
>>> c = Counter()
>>> c["goodbye"]+=1
>>> c["and thank you"]=42
>>> c["for the fish"]-=5
>>> c
Counter({''and thank you'': 42, ''goodbye'': 1, ''for the fish'': -5})
Algunas características adicionales
>>> c.most_common()[:2]
[(''and thank you'', 42), (''goodbye'', 1)]
Para obtener más información, consulte PyMOTW - Colecciones - Tipos de datos de contenedores y documentación de Python - colecciones
Me parece un poco más elegante usar partial
:
import functools
dd_int = functools.partial(defaultdict, int)
defaultdict(dd_int)
Por supuesto, esto es lo mismo que un lambda.
Otros han respondido correctamente su pregunta de cómo hacer que funcione lo siguiente:
for x in stuff:
d[x.a][x.b] += x.c_int
Una alternativa sería usar tuplas para llaves:
d = defaultdict(int)
for x in stuff:
d[x.a,x.b] += x.c_int
# ^^^^^^^ tuple key
Lo bueno de este enfoque es que es simple y se puede expandir fácilmente. Si necesita una asignación de tres niveles de profundidad, solo use una tupla de tres elementos para la clave.
Sí, así:
defaultdict(lambda: defaultdict(int))
Cuando intente acceder a una clave que no existe, se llamará al argumento de un defaultdict
(en este caso es lambda: defaultdict(int)
). El valor de retorno se establecerá como el nuevo valor de esta clave, lo que significa que en nuestro caso el valor de d[Key_doesnt_exist]
será defaultdict(int)
.
Si intenta acceder a una clave desde este último valor predeterminado, es decir, d[Key_doesnt_exist][Key_doesnt_exist]
, devolverá 0, que es el valor de retorno del argumento del último valor predeterminado, es decir, int()
.