2008-11-29 11 views
26

Tengo una lista de datos que tiene el siguiente aspecto:Almacenamiento y actualización de listas en diccionarios Python: ¿por qué sucede esto?

// timestep,x_position,y_position 
0,4,7 
0,2,7 
0,9,5 
0,6,7 
1,2,5 
1,4,7 
1,9,0 
1,6,8 

... y quiero hacer este aspecto:

0, (4,7), (2,7), (9,5), (6,7) 
1, (2,5), (4,7), (9,0), (6.8) 

Mi plan era usar un diccionario, donde el el valor de t es la clave del diccionario, y el valor en contra de la clave sería una lista. Podría agregar cada uno (x, y) a la lista. Algo como:

# where t = 0, c = (4,7), d = {} 

# code 1 
d[t].append(c) 

Ahora esto hace que el IDLE falle. Sin embargo, si lo hago:

# code 2 
d[t] = [] 
d[t].append(c) 

... esto funciona.

Entonces la pregunta es: ¿por qué funciona el código 2, pero el código 1 no?

PD Cualquier mejora en lo que planeo hacer sería de gran interés !! Creo que tendré que revisar el diccionario en cada ciclo a través de la entrada para ver si la clave del diccionario ya existe, supongo que usando algo como max (d.keys()): si está allí, anexar datos, si no crear la lista vacía como el valor del diccionario, y luego anexar datos en el siguiente ciclo. mirada

+0

No muy significativo. Por favor ingrese el mensaje de error real. –

Respuesta

72

Vamos a

d[t].append(c) 

¿Cuál es el valor de d[t]? Intentalo.

d = {} 
t = 0 
d[t] 

¿Qué obtienes? Oh. No hay nada en d que tenga una clave de t.

Ahora intenta esto.

d[t] = [] 
d[t] 

Ahh. Ahora hay algo en d con una clave de t.

Hay varias cosas que puede hacer.

  1. Uso ejemplo 2.
  2. Uso setdefault. d.setdefault(t,[]).append(c).
  3. Use collections.defaultdict. Utilizaría un defaultdict(list) en lugar de un diccionario simple, {}.

Editar 1. Optimización

Dadas las líneas de entrada de un archivo en el formulario de arriba: ts, x, y, el proceso de agrupación es innecesaria. No hay razón para pasar de una lista simple de (ts, x, y) a una lista más compleja de de (ts, (x, y), (x, y), (x, y), ...). La lista original se puede procesar exactamente como llegó.

d= collections.defaultdict(list) 
for ts, x, y in someFileOrListOrQueryOrWhatever: 
    d[ts].append((x,y)) 

Editar 2. Respuesta Pregunta

"cuando la inicialización de un diccionario, es necesario contar el diccionario lo que la estructura de datos clave-valor se verá así?"

No estoy seguro de lo que significa la pregunta. Dado que todos los diccionarios son pares clave-valor, la pregunta no es muy clara. Por lo tanto, revisaré las tres alternativas, que pueden responder a la pregunta.

Ejemplo 2.

inicialización

d= {} 

Uso

if t not in d: 
    d[t] = list() 
d[t].append(c) 

Cada valor del diccionario debe ser inicializado a alguna estructura útil. En este caso, verificamos si la clave está presente; cuando falta la clave, creamos la clave y asignamos una lista vacía.

setDefault

inicialización

d= {} 

Uso

d.setdefault(t,list()).append(c) 

En este caso, se explota el método setdefault ya sea a buscar un valor asociado a una clave o crear un nuevo valor asociado con una clave faltante.

predeterminado dict

inicialización

import collections 
d = collections.defaultdict(list) 

Uso

d[t].append(c) 

El defaultdict utiliza una función de inicialización para las claves que faltan. En este caso, proporcionamos la función list para que se cree una nueva lista vacía para una clave faltante.

+0

¿Significa esto que al inicializar un diccionario, debe decirle al diccionario cómo se verá la estructura de datos clave-valor? Lo sentimos, procedentes de un fondo de Perl que no he utilizado en la ira en años, por lo que puede estar pasando recuerdos rotos, ya que estaba seguro de que podría hacerlo de forma anónima. – user41121

1
dict=[] //it's not a dict, it's a list, the dictionary is dict={} 
elem=[1,2,3] 
dict.append(elem) 

puede acceder al elemento individual de esta manera:

print dict[0] // 0 is the index 

la salida será:

[1, 2, 3] 
+1

Python es lo suficientemente confuso con su horquillado irregular para agregar a ella mediante la adopción de un nombre de función (dict() debe devolver un dict vacío) similar a una estructura de datos y que sea una variable. – jibay

11

Creo que desee utilizar setdefault. Es un poco raro de usar, pero hace exactamente lo que necesita.

d.setdefault(t, []).append(c) 

El método .setdefault devolverá el elemento (en nuestro caso, una lista) que está destinado a la dict clave t si existe esa tecla. Si no lo hace, enlazará una lista vacía a la clave t y la devolverá. Entonces, de cualquier forma, habrá una lista para que el método .append pueda agregar la tupla c a.

1

En el caso que sus datos no está ya ordenadas según criterios deseados, aquí está el código que podría ayudar a agrupar los datos:

#!/usr/bin/env python 
""" 
$ cat data_shuffled.txt 
0,2,7 
1,4,7 
0,4,7 
1,9,0 
1,2,5 
0,6,7 
1,6,8 
0,9,5 
""" 
from itertools import groupby 
from operator import itemgetter 

# load the data and make sure it is sorted by the first column 
sortby_key = itemgetter(0) 
data = sorted((map(int, line.split(',')) for line in open('data_shuffled.txt')), 
       key=sortby_key) 

# group by the first column 
grouped_data = [] 
for key, group in groupby(data, key=sortby_key): 
    assert key == len(grouped_data) # assume the first column is 0,1, ... 
    grouped_data.append([trio[1:] for trio in group]) 

# print the data 
for i, pairs in enumerate(grouped_data): 
    print i, pairs 

salida: "Idle falla"

0 [[2, 7], [4, 7], [6, 7], [9, 5]] 
1 [[4, 7], [9, 0], [2, 5], [6, 8]] 
Cuestiones relacionadas