comprensión de la lista de Python para producir dos valores en una iteración

3 minutos de lectura

avatar de usuario
usuario1629366

Quiero generar una lista en python de la siguiente manera:

[1, 1, 2, 4, 3, 9, 4, 16, 5, 25 .....]

Te habrías dado cuenta, no es más que n, n*n

Intenté escribir una lista de comprensión de este tipo en python de la siguiente manera:

lst_gen = [i, i*i for i in range(1, 10)]

Pero al hacer esto, da un error de sintaxis.

¿Cuál sería una buena manera de generar la lista anterior a través de la comprensión de listas?

avatar de usuario
Ashwini Chaudhary

Usar itertools.chain.from_iterable:

>>> from itertools import chain
>>> list(chain.from_iterable((i, i**2) for i in xrange(1, 6)))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25]

O también puedes usar un generador función:

>>> def solve(n):
...     for i in xrange(1,n+1):
...         yield i
...         yield i**2

>>> list(solve(5))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25]

La pregunta es antigua, pero solo para el lector curioso, propongo otra posibilidad: como se indicó en la primera publicación, puede hacer fácilmente un par (i, i ** 2) de una lista de números. Entonces quieres aplanar a esta pareja. Así que solo agregue la operación de aplanar en su comprensión.

[x for i in range(1, 10) for x in (i,i**2)]

  • Esta fue la solución más prometedora que tenía en mente antes de buscar la pregunta y sé que es la solución que elegí para el problema. — Excepto que en realidad usaré un bucle y append.

    – loxaxs

    30 de mayo de 2018 a las 13:44


Un truco poco conocido: las listas por comprensión pueden tener múltiples cláusulas for.

Por ejemplo:

>>> [10*x+y for x in range(4) for y in range(3)]
[0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32]

En tu caso particular, podrías hacer:

>>> [x*x if y else x for x in range(5) for y in range(2)]
[0, 0, 1, 1, 2, 4, 3, 9, 4, 16]

Las comprensiones de listas generan una elemento a la vez. Sus opciones son, en cambio, cambiar su ciclo para generar solo un valor a la vez:

[(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]

o para producir tuplas y luego aplanar la lista usando itertools.chain.from_iterable():

from itertools import chain

list(chain.from_iterable((i, i*i) for i in range(1, 10)))

Producción:

>>> [(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]
>>> list(chain.from_iterable((i, i*i) for i in range(1, 10)))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

avatar de usuario
juan sala

Puede crear una lista de listas y luego usar reducir para unirlas.

print [[n,n*n] for n in range (10)]

[[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

print reduce(lambda x1,x2:x1+x2,[[n,n*n] for n in range (10)])

[0, 0, 1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

 print reduce(lambda x1,x2:x1+x2,[[n**e for e in range(1,4)]\
 for n in range (1,10)])

[1, 1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5, 25, 125, 6, 36, 216, 7, 49, 343, 8, 64, 512, 9, 81, 729]

Reduce toma una expresión invocable que toma dos argumentos y procesa una secuencia comenzando con los dos primeros elementos. El resultado de la última expresión se usa luego como el primer elemento en llamadas posteriores. En este caso, cada lista se agrega una tras otra a la primera lista en la lista de listas y luego esa lista se devuelve como resultado.

Las comprensiones de lista llaman implícitamente al mapa con una expresión lambda usando la variable y la secuencia definida por “por variable en expresión “secuencia”. Lo siguiente es el mismo tipo de cosa.

map(lambda n:[n,n*n],range(1,10))

[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

No conozco una expresión de Python más natural para reducir.

avatar de usuario
Joran Beasley

lst_gen = sum([(i, i*i) for i in range(1, 10)],())

oh, debería mencionar que la suma probablemente rompe la regla de una iteración 🙁

avatar de usuario
irúvar

Otra opción, puede parecer perversa para algunos

>>> from itertools import izip, tee
>>> g = xrange(1, 11)
>>> x, y = tee(g)
>>> y = (i**2 for i in y)
>>> z = izip(x, y)
>>> output = []
>>> for k in z:
...     output.extend(k)
... 
>>> print output
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81, 10, 100]

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad