128 votes

Python (compréhension de la liste): renvoyer deux éléments (ou plus) pour chaque élément

Est-il possible de retourner 2 articles (ou plus) pour chaque article dans une liste de compréhension?

Ce que je veux (exemple):

 [f(x), g(x) for x in range(n)]
 

devrait retourner [f(0), g(0), f(1), g(1), ..., f(n-1), g(n-1)]

Donc, quelque chose pour remplacer ce bloc de code:

 result = list()
for x in range(n):
    result.add(f(x))
    result.add(g(x))
 

170voto

ninjagecko Points 25709

Compréhension de la liste double:

 [f(x) for x in range(5) for f in (f1,f2)]
 

Démo:

 >>> f1 = lambda x: x
>>> f2 = lambda x: 10*x

>>> [f(x) for x in range(5) for f in (f1,f2)]
[0, 0, 1, 10, 2, 20, 3, 30, 4, 40]
 

62voto

jamylak Points 38094
 >>> from itertools import chain
>>> f = lambda x: x + 2
>>> g = lambda x: x ** 2
>>> list(chain.from_iterable((f(x), g(x)) for x in range(3)))
[2, 0, 3, 1, 4, 4]
 

Horaires:

 from timeit import timeit

f = lambda x: x + 2
g = lambda x: x ** 2

def fg(x):
    yield f(x)
    yield g(x)

print timeit(stmt='list(chain.from_iterable((f(x), g(x)) for x in range(3)))',
             setup='gc.enable(); from itertools import chain; f = lambda x: x + 2; g = lambda x: x ** 2')

print timeit(stmt='list(chain.from_iterable(fg(x) for x in range(3)))',
             setup='gc.enable(); from itertools import chain; from __main__ import fg; f = lambda x: x + 2; g = lambda x: x ** 2')

print timeit(stmt='[func(x) for x in range(3) for func in (f, g)]',
             setup='gc.enable(); f = lambda x: x + 2; g = lambda x: x ** 2')


print timeit(stmt='list(chain.from_iterable((f(x), g(x)) for x in xrange(10**6)))',
             setup='gc.enable(); from itertools import chain; f = lambda x: x + 2; g = lambda x: x ** 2',
             number=20)

print timeit(stmt='list(chain.from_iterable(fg(x) for x in xrange(10**6)))',
             setup='gc.enable(); from itertools import chain; from __main__ import fg; f = lambda x: x + 2; g = lambda x: x ** 2',
             number=20)

print timeit(stmt='[func(x) for x in xrange(10**6) for func in (f, g)]',
             setup='gc.enable(); f = lambda x: x + 2; g = lambda x: x ** 2',
             number=20)
 

2.69210777094

3.13900787874

1.62461071932

25.5944058287

29.2623711793

25.7211849286

17voto

ninjagecko Points 25709
sum( ([f(x),g(x)] for x in range(n)), [] )

C'est l'équivalent d' [f(1),g(1)] + [f(2),g(2)] + [f(3),g(3)] + ...

Vous pouvez aussi penser à ce que:

def flatten(list):
    ...

flatten( [f(x),g(x)] for x in ... )

remarque: La bonne façon est d'utiliser des itertools.chain.from_iterable ou la double compréhension de liste. (Il ne nécessite pas de recréer la liste de tous les +, a donc O(N) plutôt que de O(N^2) les performances.) Je vais encore utiliser sum(..., []) quand je veux un rapide one-liner ou je suis pressé, ou lorsque le nombre de termes combiné est bornée (par exemple, < = 10). C'est pourquoi j'ai toujours le mentionner ici, avec cette mise en garde. Vous pouvez également utiliser les tuples: ((f(x),g(x)) for ...), () (ou par khachik commentaire, d'avoir un générateur de fg(x) ce qui donne un deux-tuple).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X