Python (List Comprehension): returning two (or more) items for each item

Is it possible to return 2 (or more) items for each item in a list comprehension?

What I want (example):

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

should return [f(0), g(0), f(1), g(1), ..., f(n-1), g(n-1)]

So, something to replace this block of code:

 result = list() for x in range(n): result.add(f(x)) result.add(g(x)) 
+54
python list-comprehension
Aug 08 2018-12-12T00:
source share
4 answers
 >>> 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] 

Timings:

 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

+39
Aug 08 '12 at 16:29
source share

Double list recognition:

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

Demo:

 >>> 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] 
+59
Aug 08 '12 at 16:50
source share
 sum( ([f(x),g(x)] for x in range(n)), [] ) 

This is equivalent to [f(1),g(1)] + [f(2),g(2)] + [f(3),g(3)] + ...

You can also think of it as:

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

Note. The correct way is to use itertools.chain.from_iterable or recognize a double list. (This does not require recreating the list on each +, so it has O (N) performance, not O (N ^ 2).) I will still use sum(..., []) when I need a quick one-line or I am in a hurry or when the number of terms is limited (for example, <= 10). That is why I still mention it here, with this warning. You can also use tuples: ((f(x),g(x)) for ...), () (or for a comment on a hacker that has a fg (x) generator that gives a two-tuple).

+7
Aug 08 2018-12-12T00:
source share

This lambda function fastens two lists into one:

 zipped = lambda L1, L2: [L[i] for i in range(min(len(L1), len(L2))) for L in (L1, L2)] 

Example:

 >>> 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] 
+1
Nov 26 '15 at 16:15
source share



All Articles