2010-07-07 8 views
83

Soy nuevo en Python y tengo una lista de años y valores para cada año. Lo que quiero hacer es verificar si el año ya existe en un diccionario y, si lo hace, agregar el valor a esa lista de valores para la clave específica.añada varios valores para una clave en el diccionario de Python

Así, por ejemplo, tengo una lista de años y tienen un valor para cada año:

2010 
2 
2009 
4 
1989 
8 
2009 
7 

Lo que quiero hacer es llenar un diccionario con los años como llaves y los números de un dígito como valores . Sin embargo, si tengo 2009 aparece dos veces, quiero añadir que el segundo valor a mi lista de valores en ese diccionario, así que quiero:

2010: 2 
2009: 4, 7 
1989: 8 

En este momento me he lo siguiente:

d = dict() 
years = [] 

(get 2 column list of years and values) 

for line in list:  
    year = line[0] 
    value = line[1] 

for line in list: 
    if year in d.keys(): 
     d[value].append(value) 
    else: 
     d[value] = value 
     d[year] = year 
+1

Otra pregunta similar: http://stackoverflow.com/questions/5378231/python-list-to-dictionary-multiple-values-per-key – River

Respuesta

116

Si puedo reformular su pregunta, lo que quiere es un diccionario con los años como claves y una matriz para cada año que contiene una lista de valores asociados con ese año, ¿no? Así es como yo lo haría:

years_dict = dict() 

for line in list: 
    if line[0] in years_dict: 
     # append the new number to the existing array at this slot 
     years_dict[line[0]].append(line[1]) 
    else: 
     # create a new array in this slot 
     years_dict[line[0]] = [line[1]] 

Lo que debe terminar con en years_dict es un diccionario que tiene el siguiente aspecto:

{ 
    "2010": [2], 
    "2009": [4,7], 
    "1989": [8] 
} 

En general, es una práctica mala programación para crear "paralela arrays ", donde los elementos están implícitamente asociados entre sí al tener el mismo índice en lugar de ser hijos propios de un contenedor que los abarca a ambos.

+14

Esta es definitivamente la forma correcta de hacerlo, aunque no necesariamente la más conciso dada la disponibilidad de trucos geniales como 'dict.setdefault()' y 'collections.defaultdict' como parte del conjunto de herramientas predeterminado disponible para las instalaciones modernas de Python. – jathanism

+2

gracias, esto era exactamente lo que necesitaba para solucionar mi problema – anon

+0

Si usa defaultdict configúrelo como una lista: dd = defaultdict (list) – sparrow

67

Lo mejor será que uses collections.defaultdict (agregado en Python 2.5). Esto le permite especificar el tipo de objeto predeterminado de una clave faltante (como list).

De modo que, en lugar de crear una clave si no existe primero y luego agregar el valor de la clave, se corta el intermediario y se agrega directamente a las claves no existentes para obtener el resultado deseado.

Un ejemplo rápido usando sus datos:

>>> from collections import defaultdict 
>>> data = [(2010, 2), (2009, 4), (1989, 8), (2009, 7)] 
>>> d = defaultdict(list) 
>>> d 
defaultdict(<type 'list'>, {}) 
>>> for year, month in data: 
...  d[year].append(month) 
... 
>>> d 
defaultdict(<type 'list'>, {2009: [4, 7], 2010: [2], 1989: [8]}) 

De esta manera usted no tiene que preocuparse acerca de si usted ha visto un dígito asociado a un año o no. Simplemente agrega y olvida, sabiendo que una clave faltante siempre será una lista. Si ya existe una clave, solo se agregará a ella.

25

Puede usar setdefault.

for line in list: 
    d.setdefault(year, []).append(value) 

Esto funciona porque setdefault devuelve la lista, así como el establecimiento en el diccionario, y debido a una lista es mutable, añadiendo a la versión devuelto por setdefault es lo mismo que anexar a la versión en el interior del propio diccionario . Si eso tiene algún sentido.

12
d = {} 

# import list of year,value pairs 

for year,value in mylist: 
    try: 
     d[year].append(value) 
    except KeyError: 
     d[year] = [value] 

La forma de Python: ¡es más fácil recibir perdón que pedir permiso!

+6

manera python es no duplicar la funcionalidad – SilentGhost

+1

No veo cómo hay duplicación aquí. –

2

Es más fácil si obtiene estos valores en una lista de tuplas. Para hacer esto, puede usar la división de listas y la función zip.

data_in = [2010,2,2009,4,1989,8,2009,7] 
data_pairs = zip(data_in[::2],data_in[1::2]) 

postal lleva un número arbitrario de las listas, en este caso las entradas de pares e impares de data_in, y los pone juntos en una tupla.

Ahora podemos usar el método setdefault.

data_dict = {} 
for x in data_pairs: 
    data_dict.setdefault(x[0],[]).append(x[1]) 

setdefault toma una clave y un valor por defecto, y devuelve cualquiera de los valores asociados, o si no hay ningún valor actual, el valor por defecto. En este caso, obtendremos una lista vacía o poblada, a la que a continuación añadiremos el valor actual.

4

Aquí es una forma alternativa de hacer esto utilizando el not in operador:

# define an empty dict 
years_dict = dict() 

for line in list: 
    # here define what key is, for example, 
    key = line[0] 
    # check if key is already present in dict 
    if key not in years_dict: 
     years_dict[key] = [] 
    # append some value 
    years_dict[key].append(some.value) 
1

Si desea una (casi) de una sola línea:

 
from collections import deque 

d = {} 
deque((d.setdefault(year, []).append(value) for year, value in source_of_data), maxlen=0) 

Usando dict.detdefault, puede encapsular la idea de "verificar si la clave ya existe y hacer una nueva lista si no es así" en una sola llamada. Esto le permite escribir una expresión del generador que es consumida por deque de la manera más eficiente posible ya que la longitud de la cola se establece en cero. El deque se descartará inmediatamente y el resultado será d.

Esto es algo que acabo de hacer por diversión. No recomiendo usarlo. Hay un tiempo y un lugar para consumir iterables arbitrarios a través de un deque, y definitivamente no es así.

+0

Si uso 'data = [(2010, 2), (2009, 4), (1989, 8), (2009, 7)]', devuelve 'deque ([])'. – Cleb

+0

@Cleb. El resultado está en 'd'. El deque debe descartarse. Su única función es procesar el generador lo más rápido posible. –

+0

Ooops, estúpido de mí; entonces funciona muy bien ... – Cleb

Cuestiones relacionadas