dequeue - python map




Python: defaultdict di defaultdict? (3)

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.

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()

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