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]