web-dev-qa-db-fra.com

compréhension de la liste python pour produire deux valeurs en une itération

Je veux générer une liste en python comme suit - 

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

Vous auriez compris, ce n'est rien d'autre que n, n*n

J'ai essayé d'écrire une telle compréhension de liste en python comme suit - 

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

Mais cela donne une erreur de syntaxe. 

Quel serait un bon moyen de générer la liste ci-dessus via une compréhension de liste?

34
user1629366

Utilisez 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]

Ou vous pouvez également utiliser un générateur :

>>> 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]
37

La question est ancienne, mais je ne propose qu’au lecteur curieux une autre possibilité: Ensuite, vous voulez aplatir ce couple. Ajoutez donc simplement l'opération d'aplatissement à votre compréhension.

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

Un truc peu connu: les compréhensions de liste peuvent avoir plusieurs clauses for.

Par exemple:

>>> [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]

Dans votre cas particulier, vous pourriez faire:

>>> [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]
6
Jonathan Mayer

Les compréhensions de liste génèrent un élément à la fois. Au lieu de cela, vos options sont de changer votre boucle pour ne générer qu'une valeur à la fois:

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

ou pour produire des nuplets puis aplatissez la liste en utilisant itertools.chain.from_iterable():

from itertools import chain

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

Sortie:

>>> [(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]
5
Martijn Pieters
lst_gen = sum([(i, i*i) for i in range(1, 10)],())

oh je devrais mentionner la somme enfreint probablement la règle d'une itération :(

5
Joran Beasley

Vous pouvez créer une liste de listes, puis utilisez réduire pour les rejoindre.

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]

Réduire prend une expression appelable qui prend deux arguments et traite une séquence en commençant par les deux premiers éléments. Le résultat de la dernière expression est ensuite utilisé comme premier élément lors des appels suivants. Dans ce cas, chaque liste est ajoutée l'une après l'autre à la première liste de la liste, puis cette liste est renvoyée.

La liste des compréhensions appelle implicitement map avec une expression lambda en utilisant la variable et la séquence définies par l'expression " pour var in sequence". Ce qui suit est le même genre de chose. 

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]]

Je ne suis pas au courant d'une expression plus naturelle de python pour réduire.

3
John Hall

Une autre option pourrait sembler perverse à certains

>>> 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]
2
iruvar

Une autre option:

reduce(lambda x,y: x + [y, y*y], range(1,10), [])
1
Matthew Plourde

Beaucoup de trucs dans ce fil. Voici un autre utilisant un générateur à une ligne sans importations

x = (lamdba : [[(yield i), (yield i**2)] for i in range(10)])()

EDIT: Cela déclenchera DeprecatedWarning dans Python 3.7 et SyntaxError dans Python 3.8: https://docs.python.org/dev/whatsnew/3.7.html#deprecated-python-behavior

0
Hielke Walinga
>>> lst_gen = [[i, i*i] for i in range(1, 10)]
>>> 
>>> lst_gen
[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
>>> 
>>> [num for elem in lst_gen for num in elem]
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

Voici ma référence http://docs.python.org/2/tutorial/datastructures.html

0
Supriya K

Essayez cette doublure

lst = [[i, i*i] for i in range(10)]
[lst.extend(i) for i in lst]

Changer les maths si nécessaire. 

ENCORE MIEUX

#Change my_range to be the number you want range() function of
start = 1
my_range = 10
lst = [i/2 if i % 2 == 0 else ((i-1)/2)**2 for i in range(start *2, my_range*2 - 1)]
0
ytpillai

Comme mentionné, itertools est la voie à suivre. Voici comment je le ferais, je le trouve plus clair:

[i if turn else i*i for i,turn in itertools.product(range(1,10), [True, False])]
0
ntg