¿Lista de comprensión en una lista anidada?

Tengo esta lista anidada:

l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']] 

Ahora, lo que quiero hacer es convertir cada elemento en una lista para flotar. Mi solución es la siguiente:

 newList = [] for x in l: for y in x: newList.append(float(y)) 

Pero, ¿se puede hacer esto usando una comprensión de lista anidada, verdad?

Lo que he hecho es:

 [float(y) for y in x for x in l] 

Pero entonces el resultado es un montón de 100 con la sum de 2400.

Cualquier solución, una explicación sería muy apreciada. ¡Gracias!

Aquí es cómo haría esto con una lista de comprensión anidada:

 [[float(y) for y in x] for x in l] 

Esto le daría una lista de listas, similar a la que comenzó excepto con flotantes en lugar de cadenas. Si desea una lista plana, entonces usaría [float(y) for x in l for y in x] .

Aquí es cómo convertir nested para bucle a comprensión de lista anidada:

introduzca la descripción de la imagen aquí

Aquí es cómo funciona la comprensión de la lista anidada:

  labcdef ↓ ↓ ↓ ↓ ↓ ↓ ↓ In [1]: l = [ [ [ [ [ [ 1 ] ] ] ] ] ] In [2]: for a in l: ...: for b in a: ...: for c in b: ...: for d in c: ...: for e in d: ...: for f in e: ...: print(float(f)) ...: 1.0 In [3]: [float(f) for a in l ...: for b in a ...: for c in b ...: for d in c ...: for e in d ...: for f in e] Out[3]: [1.0] #Which can be written in single line as In [4]: [float(f) for a in l for b in a for c in b for d in c for e in d for f in e] Out[4]: [1.0] 
 >>> l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']] >>> new_list = [float(x) for xs in l for x in xs] >>> new_list [40.0, 20.0, 10.0, 30.0, 20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0, 30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0] 

No estoy seguro de cuál es su salida deseada, pero si está utilizando la comprensión de lista, el orden sigue el orden de los bucles nesteds, que tiene al revés. Así que tengo lo que creo que quieres con:

 [float(y) for x in l for y in x] 

El principio es: use el mismo orden que usaría al escribirlo como nested para bucles.

Como llego un poco tarde aquí, pero quería compartir cómo funciona realmente la comprensión de listas, especialmente la comprensión de listas anidadas:

  New_list= [[float(y) for x in l] 

es en realidad igual que

 New_list=[] for x in l: New_list.append(x) 

Y ahora la lista de comprensión anidada:

 [[float(y) for y in x] for x in l] 

es igual que

 new_list=[] for x in l: sub_list=[] for y in x: sub_list.append(float(y)) new_list.append(sub_list) print(new_list) 

salida:

 [[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]] 

Si no le gustan las comprensiones de listas anidadas, también puede hacer uso de la función de mapa ,

 >>> from pprint import pprint >>> l = l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']] >>> pprint(l) [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']] >>> float_l = [map(float, nested_list) for nested_list in l] >>> pprint(float_l) [[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]] 

Tenía un problema similar que resolver, así que me encontré con esta pregunta. Hice una comparación de desempeño de la respuesta de Andrew Clark y Narayan que me gustaría compartir.

La diferencia principal entre dos respuestas es cómo se repiten en las listas internas. Uno de ellos utiliza el mapa integrado, mientras que otro utiliza la comprensión de lista. La función de mapa tiene una ligera ventaja de rendimiento para su comprensión de lista equivalente si no requiere el uso de lambdas . Entonces, en el contexto de esta pregunta, el map debería tener un rendimiento ligeramente mejor que la comprensión de la lista.

Vamos a hacer una prueba de rendimiento para ver si es realmente cierto. Usé la versión 3.5.0 de python para realizar todas estas pruebas. En el primer conjunto de pruebas me gustaría mantener los elementos por lista de 10 y variar el número de listas de 10 a 100,000

 >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10]" >>> 100000 loops, best of 3: 15.2 usec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10]" >>> 10000 loops, best of 3: 19.6 usec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100]" >>> 100000 loops, best of 3: 15.2 usec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100]" >>> 10000 loops, best of 3: 19.6 usec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*1000]" >>> 1000 loops, best of 3: 1.43 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*1000]" >>> 100 loops, best of 3: 1.91 msec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10000]" >>> 100 loops, best of 3: 13.6 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10000]" >>> 10 loops, best of 3: 19.1 msec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100000]" >>> 10 loops, best of 3: 164 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100000]" >>> 10 loops, best of 3: 216 msec per loop 

introduzca la descripción de la imagen aquí

En el siguiente conjunto de pruebas, me gustaría boost el número de elementos por listas a 100 .

 >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10]" >>> 10000 loops, best of 3: 110 usec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10]" >>> 10000 loops, best of 3: 151 usec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100]" >>> 1000 loops, best of 3: 1.11 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100]" >>> 1000 loops, best of 3: 1.5 msec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*1000]" >>> 100 loops, best of 3: 11.2 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*1000]" >>> 100 loops, best of 3: 16.7 msec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10000]" >>> 10 loops, best of 3: 134 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10000]" >>> 10 loops, best of 3: 171 msec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100000]" >>> 10 loops, best of 3: 1.32 sec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100000]" >>> 10 loops, best of 3: 1.7 sec per loop 

introduzca la descripción de la imagen aquí

Vamos a dar un paso valiente y modificar el número de elementos en las listas para que sean 1000

 >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10]" >>> 1000 loops, best of 3: 800 usec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10]" >>> 1000 loops, best of 3: 1.16 msec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100]" >>> 100 loops, best of 3: 8.26 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100]" >>> 100 loops, best of 3: 11.7 msec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*1000]" >>> 10 loops, best of 3: 83.8 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*1000]" >>> 10 loops, best of 3: 118 msec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10000]" >>> 10 loops, best of 3: 868 msec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10000]" >>> 10 loops, best of 3: 1.23 sec per loop >>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100000]" >>> 10 loops, best of 3: 9.2 sec per loop >>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100000]" >>> 10 loops, best of 3: 12.7 sec per loop 

introduzca la descripción de la imagen aquí

A partir de estas pruebas, podemos concluir que el map tiene un beneficio de rendimiento sobre la comprensión de la lista en este caso. Esto también es aplicable si intentas lanzar a int o str . Para un pequeño número de listas con menos elementos por lista, la diferencia es insignificante. Para listas más grandes con más elementos por lista, es posible que desee utilizar el map lugar de la comprensión de la lista, pero depende totalmente de las necesidades de la aplicación.

Sin embargo, personalmente considero que la comprensión de listas es más legible e idiomática que el map . Es un estándar de facto en python. Generalmente, las personas son más competentes y cómodas (especialmente principiantes) en el uso de la comprensión de listas que en el map .

Sí, puedes hacerlo con ese código:

 l = [[float(y) for y in x] for x in l] 

Este problema se puede resolver sin usar el bucle. Solo un código de línea será suficiente para esto. El uso del mapa nested con la función lambda también funcionará aquí.

 l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']] map(lambda x:map(lambda y:float(y),x),l) 

Y la lista de salida sería la siguiente:

 [[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]] 

La mejor manera de hacer esto en mi opinión es utilizar el paquete itertools de python.

 >>>import itertools >>>l1 = [1,2,3] >>>l2 = [10,20,30] >>>[l*2 for l in itertools.chain(*[l1,l2])] [2, 4, 6, 20, 40, 60] 

Sí, puedes hacer lo siguiente.

 [[float(y) for y in x] for x in l] 
  deck = [] for rank in ranks: for suit in suits: deck.append(('%s%s')%(rank, suit)) 

Esto se puede lograr utilizando la comprensión de la lista:

 [deck.append((rank,suit)) for suit in suits for rank in ranks ]