2011-08-18 8 views
5

Así que tienen una matriz de la forma siguiente:¿Por qué no puedo obtener dos listas de una lista de comprensión?

[(1, u'first_type', u'data_gid_1'), 
(2, u'first_type', u'data_gid_2'), 
(3, u'first_type', u'data_gid_3'), 
(4, u'first_type', u'data_gid_4')] 

Ahora quiero extraer el primer y el último elemento de cada lista en el interior en listas separadas. Entonces si lo hago:

>>> ids = [dat[0] for dat in all_data] 
>>> gds = [dat[2] for dat in all_data] 

Esto funciona como esperaba. Sin embargo yo estaba tratando de fusionar estos dos en una llamada, algo así como:

(ids, gds) = [(dat[0], dat[2]) for dat in all_data] 

Sin embargo, esto falla con un: ValueError: too many values to unpack

Así podría alguien explicar por qué ocurre esto y si lo que estoy tratando de hacer incluso es posible

Saludos, Bogdan

+1

¿Hay algún problema al dejarlo como dos líneas? Quiero decir, a veces es agradable ser claro. –

+1

No pasa nada, esa sigue siendo la solución que estoy usando, solo quería entender por qué estaba obteniendo el error para usos futuros. – Bogdan

+0

@Bogdan Eso es verdaderamente honorable. Te daría un +1 por ese comentario. – cwallenpoole

Respuesta

8

No funciona porque la longitud de [(dat[0], dat[2]) for dat in all_data] es la misma que la longitud de all_data, que no es la misma longitud que la tupla (ids, gds).

Tal vez puedas probar:

(ids, gds) = zip(*[(dat[0], dat[2]) for dat in all_data]) 

o incluso más corto:

(ids, gds) = zip(*all_data)[::2] 

Como se señaló en otra respuesta, ids y gds ahora serán tuplas, así que si necesitas listas, hacer como esto:

(ids, gds) = map(list, zip(*all_data)[::2]) 



La zip(*something) es una expresión bastante frecuente en python. Si nos fijamos en una lista de listas como una matriz, es decir

l = [[1, 2, 3], 
    [4, 5, 6]] 

Entonces zip(*l) transpone esa matriz:

zip(*l) == [(1, 4), 
      (2, 5), 
      (3, 6)] 

Los * funciona así: some_func(*some_list)descomprimesome_list de manera que la función está en efecto llamado con los elementos de some_list como argumentos. Entonces zip(*l) es lo mismo que zip([1, 2, 3], [4, 5, 6]). Here's la parte relevante del tutorial de Python.

zip actúa como un zipper, de ahí el nombre, por lo que devuelve una lista con estos elementos: una tupla de todos los primeros elementos de los argumentos dados, seguido de una tupla de todos los segundos elementos, etc.

+1

Agradable. Aunque una explicación un poco mejor para ayudar al OP: "Demasiados valores para descomprimir" se produce porque está tratando de asignar una lista de 4 elementos a una tupla de 2 elementos ". +1. –

+0

Gracias por las entradas. Tengo ahora. – Bogdan

+0

Quería preguntar qué es exactamente lo que hace zip(). Gracias por aclararlo. Aceptará tan pronto como el tiempo expire. – Bogdan

1

[(dat[0], dat[2]) for dat in all_data] significa que está creando una lista de tuplas (dat[0],dat[2]). No significa que tiene dos listas, una de d[0] y otra de d[2].

Puede simplemente usar zip, pero eso dará como resultado tuplas.Si desea listas, se le tiene que aplicar list al resultado:

(ids, gds) = map(list,zip(*[(dat[0], dat[2]) for dat in a])) 
4

código de abajo también lo hará el truco:

data = [(1, u'first_type', u'data_gid_1'), 
(2, u'first_type', u'data_gid_2'), 
(3, u'first_type', u'data_gid_3'), 
(4, u'first_type', u'data_gid_4')] 

ids, gds = ([row[i] for row in data] for i in [0,2]) 
0

Dado que va a crear dos listas separadas, intente esto:

ids, dgs = [(dat[0]) for dat in all_data], [(dat[2]) for dat in all_data] 

o puede descomprimirlo en una única lista con el comando que utilizó:

x = [(dat[0], dat[2]) for dat in all_data] 
Cuestiones relacionadas