2014-10-14 22 views
29

Esiste un modo più elegante per scrivere questo codice?Aggiunta all'elenco in dizionario Python

Quello che sto facendo: ho le chiavi e le date. Possono esserci un numero di date assegnato a un tasto e quindi sto creando un dizionario di liste di date per rappresentarlo. Il seguente codice funziona bene, ma speravo in un metodo più elegante e Pythonic.

dates_dict = dict() 
for key, date in cur: 
    if key in dates_dict: 
     dates_dict[key].append(date) 
    else: 
     dates_dict[key] = [date] 

Mi aspettavo che il seguito funzionasse, ma continuo a ricevere un NoneType non ha alcun errore di aggiunta di attributi.

dates_dict = dict() 
for key, date in cur: 
    dates_dict[key] = dates_dict.get(key, []).append(date) 

Questo probabilmente ha qualcosa a che fare con il fatto che

print([].append(1)) 
None 

ma perché?

+2

Si dovrebbe guardare in [ 'collections.defaultdict'] (https://docs.python.org/2/library/collections.html#collections.defaultdict) – CoryKramer

+0

potresti provare ad usare extend() invece di append() – weefwefwqg3

risposta

48

list.append rendimenti None, in quanto si tratta di un'operazione sul posto e si assegnano di nuovo a dates_dict[key]. Quindi, la prossima volta che esegui dates_dict.get(key, []).append, stai effettivamente facendo None.append. Questo è il motivo per cui sta fallendo. Invece, si può semplicemente fare

dates_dict.setdefault(key, []).append(date) 

Ma, abbiamo collections.defaultdict solo per questo scopo. Si può fare qualcosa di simile

from collections import defaultdict 
dates_dict = defaultdict(list) 
for key, date in cur: 
    dates_dict[key].append(date) 

Questo creerà un nuovo oggetto lista, se il key non si trova nel dizionario.

Nota: Poiché lo defaultdict creerà un nuovo elenco se la chiave non è stata trovata nel dizionario, questo avrà effetti collaterali non intenzionali. Ad esempio, se desideri semplicemente recuperare un valore per la chiave, che non è lì, creerà un nuovo elenco e lo restituirà.

+1

@chepner: Si noti che '__missing __()' non viene chiamato per nessuna operazione oltre a '__getitem __()'. Ciò significa che 'get()', come i dizionari normali, restituirà 'None' come predefinito piuttosto che usare 'default_factory' ie,' chiave in date_dict' e 'dates_dict.get (chiave)' funziona come previsto – jfs

+0

Proprio come azione supplementare.Ho finito per usare setdefault perché questo mi ha fatto esattamente quello che volevo senza un'importazione extra. Grazie per l'aiuto –

+0

La tua spiegazione del perché '[] .append' restituisce 'Nessuno' non ha senso per me. Se lo assegni o stampi immediatamente, perché è importante che sia un'operazione sul posto? Perché 'dates_dict.get (chiave, []). Append' produce 'None' a meno di' dates_dict [key] == None'? – cfwschmidt

2

dates_dict[key] = dates_dict.get(key, []).append(date) set dates_dict[key] a None come list.append restituisce None.

In [5]: l = [1,2,3] 

In [6]: var = l.append(3) 

In [7]: print var 
None 

Si dovrebbe usare collections.defaultdict

import collections 
dates_dict = collections.defaultdict(list) 
+0

Sì, è quello che pensavo. Poiché non è stato restituito alcun valore. Restituirà None come predefinito. Grazie –

+0

@MichaelMurphy, usare defaultdict sarà il modo più efficiente per fare ciò che vuoi –

11

C'è un modo più elegante per scrivere questo codice?

Uso collections.defaultdict:

from collections import defaultdict 

dates_dict = defaultdict(list) 
for key, date in cur: 
    dates_dict[key].append(date)