Python(列表理解):为每个项目返回两个(或更多)项目
是否有可能为列表理解中的每个项目返回2个(或更多)项目?
我想要什么(例如):
[f(x), g(x) for x in range(n)]
应该返回[f(0), g(0), f(1), g(1), ..., f(n-1), g(n-1)]
所以,有些东西要取代这个代码块:
result = list() for x in range(n): result.add(f(x)) result.add(g(x))
>>> 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]
时序:
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
双列表理解:
[f(x) for x in range(5) for f in (f1,f2)]
演示:
>>> 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]
sum( ([f(x),g(x)] for x in range(n)), [] )
这相当于[f(1),g(1)] + [f(2),g(2)] + [f(3),g(3)] + ...
你也可以把它想成:
def flatten(list): ... flatten( [f(x),g(x)] for x in ... )
注意:正确的方法是使用itertools.chain.from_iterable
或双列表理解。 (它不需要在每个+上重新创build列表,因此具有O(N)性能,而不是O(N ^ 2)性能)。当我想要快速的时候sum(..., [])
仍然会使用sum(..., [])
或者我很着急,或者当合并的条款数量有限时(例如<= 10)。 这就是为什么我仍然在这里提到它,这个警告。 你也可以使用元组: ((f(x),g(x)) for ...), ()
(或者每个khachik的注释,生成一个二元组的生成器fg(x))。
这个lambda函数将两个列表压缩成一个:
zipped = lambda L1, L2: [L[i] for i in range(min(len(L1), len(L2))) for L in (L1, L2)]
例:
>>> 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]