Python crea un dizionario di liste


214

Voglio creare un dizionario i cui valori sono elenchi. Per esempio:

{
  1: ['1'],
  2: ['1','2'],
  3: ['2']
}

Se lo faccio:

d = dict()
a = ['1', '2']
for i in a:
    for j in range(int(i), int(i) + 2): 
        d[j].append(i)

Ottengo un KeyError, perché d [...] non è un elenco. In questo caso, posso aggiungere il seguente codice dopo l'assegnazione di a per inizializzare il dizionario.

for x in range(1, 4):
    d[x] = list()

C'è un modo migliore per farlo? Diciamo che non conosco le chiavi di cui avrò bisogno finché non sarò nel secondo forciclo. Per esempio:

class relation:
    scope_list = list()
...
d = dict()
for relation in relation_list:
    for scope_item in relation.scope_list:
        d[scope_item].append(relation)

Un'alternativa sarebbe quindi sostituire

d[scope_item].append(relation)

con

if d.has_key(scope_item):
    d[scope_item].append(relation)
else:
    d[scope_item] = [relation,]

Qual è il modo migliore per gestirlo? Idealmente, aggiungere sarebbe "semplicemente funzionante". Esiste un modo per esprimere che desidero un dizionario di elenchi vuoti, anche se non conosco tutte le chiavi quando creo l'elenco?

Risposte:


278

Puoi usare defaultdict :

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> a = ['1', '2']
>>> for i in a:
...   for j in range(int(i), int(i) + 2):
...     d[j].append(i)
...
>>> d
defaultdict(<type 'list'>, {1: ['1'], 2: ['1', '2'], 3: ['2']})
>>> d.items()
[(1, ['1']), (2, ['1', '2']), (3, ['2'])]

1
Anche altri dizionari del collectionsmodulo funzionano in questo modo, ad esempio collections.OrderedDict.
txsaw1,

2
Oh. Questo è fantastico E non è necessario inizializzare su '= []'. Roba buona!
Wilmer E. Henao,

1
NameError: name 'a' is not defined
S Andrew,

51

Puoi costruirlo con la comprensione dell'elenco in questo modo:

>>> dict((i, range(int(i), int(i) + 2)) for i in ['1', '2'])
{'1': [1, 2], '2': [2, 3]}

E per la seconda parte della tua domanda usa defaultdict

>>> from collections import defaultdict
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
        d[k].append(v)

>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

32

Puoi usare setdefault:

d = dict()
a = ['1', '2']
for i in a:
    for j in range(int(i), int(i) + 2): 
        d.setdefault(j, []).append(i)

print d  # prints {1: ['1'], 2: ['1', '2'], 3: ['2']}

La funzione piuttosto strana setdefaultdice "Ottieni il valore con questa chiave, o se quella chiave non c'è, aggiungi questo valore e poi restituiscilo."

Come altri hanno giustamente sottolineato, defaultdictè una scelta migliore e più moderna. setdefaultè ancora utile nelle versioni precedenti di Python (precedenti alla 2.5).


2
Funziona, ma di solito è preferibile utilizzare defaultdict quando è disponibile.
David Z,

@David, sì, setdefault non è stato il pezzo più brillante del design, mi dispiace - non è quasi mai la scelta migliore. Penso che noi (i committer di Python) abbiamo riscattato la nostra reputazione collettiva con Collections.defaultdict, comunque ;-).
Alex Martelli,

@DavidZ, setdefault è diverso da defaultdict, in quanto è più flessibile: per il resto, come si specificano valori predefiniti diversi per le diverse chiavi del dizionario?
Alex Gidan,

@AlexGidan È vero, ma non particolarmente rilevante per questa domanda.
David Z,

Questa risposta è utile anche quando è necessario un OrderedDict e un valore predefinito.
nimcap

2

Alla tua domanda è già stata data una risposta, ma IIRC puoi sostituire linee come:

if d.has_key(scope_item):

con:

if scope_item in d:

Cioè, driferimenti d.keys()in quella costruzione. A volte defaultdictnon è l'opzione migliore (ad esempio, se si desidera eseguire più righe di codice dopo quelle elseassociate a quanto sopra if) e trovo che la insintassi sia più facile da leggere.


2

Personalmente, utilizzo JSON per convertire le cose in stringhe e viceversa. Stringhe ho capito.

import json
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
mydict = {}
hash = json.dumps(s)
mydict[hash] = "whatever"
print mydict
#{'[["yellow", 1], ["blue", 2], ["yellow", 3], ["blue", 4], ["red", 1]]': 'whatever'}

1

il modo semplice è:

a = [1,2]
d = {}
for i in a:
  d[i]=[i, ]

print(d)
{'1': [1, ], '2':[2, ]}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.