dequeue - python map




Python: defaultdict di defaultdict? (3)

C'è un modo per avere un defaultdict(defaultdict(int)) per far funzionare il seguente codice?

for x in stuff:
    d[x.a][x.b] += x.c_int

d deve essere costruito ad-hoc, a seconda degli elementi xa e xb .

Potrei usare:

for x in stuff:
    d[x.a,x.b] += x.c_int

ma poi non sarei in grado di usare:

d.keys()
d[x.a].keys()

Altri hanno risposto correttamente alla tua domanda su come ottenere il seguente lavoro:

for x in stuff:
    d[x.a][x.b] += x.c_int

Un'alternativa sarebbe usare le tuple per le chiavi:

d = defaultdict(int)
for x in stuff:
    d[x.a,x.b] += x.c_int
    # ^^^^^^^ tuple key

La cosa bella di questo approccio è che è semplice e può essere facilmente ampliato. Se hai bisogno di mappare tre livelli in profondità, usa solo una tupla di tre elementi per la chiave.


Il parametro per il costruttore defaultdict è la funzione che verrà chiamata per la costruzione di nuovi elementi. Quindi usiamo un lambda!

>>> from collections import defaultdict
>>> d = defaultdict(lambda : defaultdict(int))
>>> print d[0]
defaultdict(<type 'int'>, {})
>>> print d[0]["x"]
0

Da Python 2.7, c'è una soluzione ancora migliore usando 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})

Alcune caratteristiche bonus

>>> c.most_common()[:2]
[('and thank you', 42), ('goodbye', 1)]

Per ulteriori informazioni, consultare PyMOTW - Raccolte - Tipi di dati del contenitore e Documentazione Python - raccolte


Trovo leggermente più elegante usare partial :

import functools
dd_int = functools.partial(defaultdict, int)
defaultdict(dd_int)

Naturalmente, questo è lo stesso di un lambda.





collections