¿Python dice cómo crear una clave o agregar un elemento a la clave?


161

Tengo un diccionario vacio Nombre: dict_x es tener claves cuyos valores son listas.

De una iteración separada, obtengo una clave (ej .:) key_123y un elemento (una tupla) para colocar en la lista del dict_xvalor de key_123.

Si esta clave ya existe, quiero agregar este elemento. Si esta clave no existe, quiero crearla con una lista vacía y luego agregarla o simplemente crearla con una tupla.

En el futuro, cuando vuelva a aparecer esta clave, ya que existe, quiero que el valor se agregue nuevamente.

Mi código consiste en esto:

Obtenga clave y valor.

Vea si la clave NO existe en dict_x.

y si no lo creas: dict_x[key] == []

Después: dict_x[key].append(value)

¿Es esta la manera de hacerlo? ¿Debo tratar de usar try/exceptbloques?

Respuestas:


254

Uso dict.setdefault():

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

ayuda (dict.setdefault) :

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

44
Solía ​​hacer esto dict_x[key] = [some_value] if not dict_x.has_key(key) else dict_x[key] + [some_value]pero esta respuesta sugiere una forma mucho mejor. De hecho, se pone set()como argumento y le permite utilizar el add()método ...
fatih_dur

66

Estas son las diversas formas de hacer esto para que pueda comparar cómo se ve y elegir lo que le gusta. Los ordené de una manera que creo que es más "pitónica" , y comenté los pros y los contras que podrían no ser obvios a primera vista:

Utilizando collections.defaultdict:

import collections
dict_x = collections.defaultdict(list)

...

dict_x[key].append(value)

Pros: Probablemente el mejor rendimiento. Contras: No disponible en Python 2.4.x.

Utilizando dict().setdefault():

dict_x = {}

...

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

Contras: Creación ineficiente de list()s no utilizados .

Utilizando 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]

Hola, ¿por qué crees que .setdefault crea diccionarios innecesarios?
Phil

2
No creo que .setdefault()crea diccionarios innecesarios. Creo que estoy creando lists innecesarios []en el segundo argumento de .setdefault()que nunca se usa si keyya existe. Podría usar dict.setdefault()(en beneficio del hashing de claves eficiente), y usar una variable para reutilizar lists no utilizados , pero eso agrega algunas líneas más de código.
antak

1
IIRC, en Python, una lista vacía en igualdad se considera una constante en el nivel de bytecode, pero esto necesita alguna confirmación por parte de un gurú de bytecode (o simplemente use el módulo de desastre).
gaborous

El uso .setdefaultcrea una búsqueda de clave donde la ausencia de dictresultados dará como resultado un KeyErrortiempo collections.defaultdict(list)crea una dictbúsqueda de clave donde la ausencia insertará un list
espacio

Intenté algo similar a collections.defaultdict en mi propio código y tuvo efectos secundarios inesperados. Por ejemplo, considere el siguiente intercambio IDLE: >>> list_dict = defaultdict (list) >>> len (list_dict) 0 >>> len (list_dict [0]) 0 >>> len (list_dict) 1 Parece que cuando Python invoca el valor predeterminado agrega la clave al diccionario sin que usted lo configure activamente, lo que creará muchas listas vacías si el valor predeterminado se usa mucho. Voy a rodar mis propias funciones de contenedor para el diccionario, ineficientes pero con suerte más predecibles.
RDBury

26

Puedes usar un defaultdict para esto.

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

Esto es un poco más eficiente que setdefaultporque no terminas creando nuevas listas que no terminas usando. Cada llamada a setdefaultva a crear una nueva lista, incluso si el elemento ya existe en el diccionario.


14

Puedes usar defaultdict en collections.

Un ejemplo de 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
Debe explicar la ventaja (muy menor) que esto tiene en presencia de ciertas excepciones; como solo código, no está claro por qué se necesita la respuesta adicional.
Davis Herring

Hola, solo una alternativa sin importaciones adicionales. Esto se puede hacer claramente con una declaración if. Solo estoy sugiriendo una alternativa usando el poder de .get () en lugar de usar dict [].
Tomas Silva Ebensperger

Las dos respuestas principales mencionan dos formas diferentes sin importación (aunque no dict.get).
Davis Herring
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.