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?
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]
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)]
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]
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]
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 :(
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.
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]
Une autre option:
reduce(lambda x,y: x + [y, y*y], range(1,10), [])
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
>>> 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
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)]
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])]