for - python list comprehension tutorial
Python(Comprensión de la lista): devolver dos(o más) elementos para cada artículo (4)
Comprensión de la lista doble:
[f(x) for x in range(5) for f in (f1,f2)]
Manifestación:
>>> 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]
¿Es posible devolver 2 (o más) artículos para cada artículo en una lista de comprensión?
Lo que quiero (ejemplo):
[f(x), g(x) for x in range(n)]
debe devolver [f(0), g(0), f(1), g(1), ..., f(n-1), g(n-1)]
Entonces, algo para reemplazar este bloque de código:
result = list()
for x in range(n):
result.add(f(x))
result.add(g(x))
Esta función lambda comprime dos listas en una sola:
zipped = lambda L1, L2: [L[i]
for i in range(min(len(L1), len(L2)))
for L in (L1, L2)]
Ejemplo:
>>> f = [x for x in range(5)]
>>> g = [x*10 for x in range(5)]
>>> zipped(f, g)
[0, 0, 1, 10, 2, 20, 3, 30, 4, 40]
>>> 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]
Tiempos:
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
sum( ([f(x),g(x)] for x in range(n)), [] )
Esto es equivalente a [f(1),g(1)] + [f(2),g(2)] + [f(3),g(3)] + ...
También puedes pensar en esto como:
def flatten(list):
...
flatten( [f(x),g(x)] for x in ... )
Nota: La forma correcta es usar itertools.chain.from_iterable
o la lista doble de comprensión. (No es necesario volver a crear la lista en cada +, por lo tanto, tiene un rendimiento de O (N) en lugar de O (N ^ 2)). Seguiré usando sum(..., [])
cuando quiera uno rápido. -liner o estoy apurado, o cuando el número de términos que se combinan es limitado (por ejemplo, <= 10). Es por eso que todavía lo menciono aquí, con esta advertencia. También puede usar tuplas: ((f(x),g(x)) for ...), ()
(o por el comentario de khachik, teniendo un generador fg (x) que produce una dos tupla).