Python dict come creare la chiave o aggiungere un elemento alla chiave?


161

Ho un dizionario vuoto. Nome: dict_x deve avere le chiavi di quali valori sono elenchi.

Da un'iterazione separata, ottengo una chiave (es:) key_123e un elemento (una tupla) da inserire nell'elenco del dict_xvalore di key_123.

Se questa chiave esiste già, voglio aggiungere questo articolo. Se questa chiave non esiste, voglio crearla con un elenco vuoto e quindi aggiungerla o semplicemente crearla con una tupla.

In futuro, quando verrà nuovamente visualizzata questa chiave, poiché esiste, voglio che il valore venga aggiunto di nuovo.

Il mio codice è composto da questo:

Ottieni chiave e valore.

Verifica se la chiave NOT esiste dict_x.

e se non crearlo: dict_x[key] == []

In seguito: dict_x[key].append(value)

È questo il modo di farlo? Devo provare a usare i try/exceptblocchi?

Risposte:


254

Utilizzare dict.setdefault():

dic.setdefault(key,[]).append(value)

aiuto (dict.setdefault) :

    setdefault(...)
        D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D

4
Lo facevo prima, dict_x[key] = [some_value] if not dict_x.has_key(key) else dict_x[key] + [some_value]ma questa risposta suggerisce un modo molto migliore. In effetti, diventa set()un argomento e ti permette di usare il add()metodo ...
fatih_dur

66

Ecco i vari modi per farlo in modo da poter confrontare l'aspetto e scegliere quello che ti piace. Li ho ordinati in un modo che ritengo più "pitonico" , e ho commentato i pro e i contro che a prima vista potrebbero non essere ovvi:

Utilizzando collections.defaultdict:

import collections
dict_x = collections.defaultdict(list)

...

dict_x[key].append(value)

Pro: Probabilmente le migliori prestazioni. Contro: non disponibile in Python 2.4.x.

Utilizzando dict().setdefault():

dict_x = {}

...

dict_x.setdefault(key, []).append(value)

Contro: creazione inefficiente di messaggi inutilizzati list().

Utilizzando try ... except:

dict_x = {}

...

try:
    values = dict_x[key]
except KeyError:
    values = dict_x[key] = []
values.append(value)

O:

try:
    dict_x[key].append(value)
except KeyError:
    dict_x[key] = [value]

Ciao, perché pensi che .setdefault crei dizionari non necessari?
Phil,

2
Non penso che .setdefault()crei dizionari inutili. Penso che sto creando lists inutili (cioè []) nel secondo argomento .setdefault()che non è mai usato se keyesiste già. Potrei usare dict.setdefault()(per il beneficio dell'hash delle chiavi efficiente), e usare una variabile per riutilizzare i messaggi inutilizzati listma ciò aggiunge qualche altra riga di codice.
antak

1
IIRC, in Python un elenco vuoto in uguaglianza è considerato una costante a livello di bytecode, ma ciò richiede una conferma da parte di un guru bytecode (o semplicemente usa il modulo disas).
gaboroso

L'utilizzo di .setdefaultcrea una dictricerca chiave assente regolare porterà ad un KeyErrorpo ' collections.defaultdict(list)crea una ricerca dictchiavi assente dove inserirà un vuoto list- penso che dovresti scegliere in base al comportamento che desideri
Chris_Rands

Ho provato qualcosa di simile a collections.defaultdict nel mio codice e ha avuto effetti collaterali inaspettati. Ad esempio, considera il seguente scambio IDLE: >>> list_dict = defaultdict (list) >>> len (list_dict) 0 >>> len (list_dict [0]) 0 >>> len (list_dict) 1 Sembra che quando Python invoca il valore predefinito aggiunge la chiave al dizionario senza che tu lo imposti attivamente, il che creerà molti elenchi vuoti se il valore predefinito viene usato molto. Avrò le mie funzioni di wrapper per il dizionario, inefficienti ma si spera più prevedibili.
RDBury

26

È possibile utilizzare un valore predefinito per questo.

from collections import defaultdict
d = defaultdict(list)
d['key'].append('mykey')

Questo è leggermente più efficiente rispetto a setdefaultquando non finisci per creare nuovi elenchi che non finisci per usare. Ogni chiamata a setdefaultcreerà un nuovo elenco, anche se l'elemento esiste già nel dizionario.


14

Puoi usare defaultdict incollections .

Un esempio da doc:

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

0
dictionary['key'] = dictionary.get('key', []) + list_to_append

1
Dovresti spiegare il vantaggio (molto minore) che questo ha in presenza di alcune eccezioni; come solo codice, non è chiaro il motivo per cui è necessaria la risposta aggiuntiva.
Davis Herring,

Ciao, solo un'alternativa senza importazioni aggiuntive. Questo può essere chiaramente fatto con un'istruzione if. Sto solo suggerendo un'alternativa usando il potere di .get () invece di usare dict [].
Tomas Silva Ebensperger

Le prime due risposte menzionano due modi diversi senza importazioni (anche se non dict.get).
Davis Herring
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.