Producing multiple items in a list comprehension

Peter Otten __peter__ at web.de
Fri May 23 03:01:20 EDT 2008


Yves Dorfsman wrote:

> Peter Otten <__peter__ at web.de> wrote:
> 
>> > A slightly similar problem: If I want to "merge," say, list1=[1,2,3]
>> > with list2=[4,5,6] to obtain [1,4,2,5,3,6], is there some clever way
>> > with "zip" to do so?
> 
>> >>> items = [None] * 6
>> >>> items[::2] = 1,2,3
>> >>> items[1::2] = 4,5,6
>> >>> items
>> [1, 4, 2, 5, 3, 6]
> 
> My problem with this solution is that you depend on knowing how many
> elements you have in each list ahead of time. 

$ python -m timeit -s"a = [1,2,3]*100; b = [4,5,6]*100; from operator import
add" "list(reduce(add, zip(a, b)))"
1000 loops, best of 3: 637 usec per loop

$ python -m timeit -s"a = [1,2,3]*100; b =
[4,5,6]*100" "items=[None]*(2*len(a)); items[::2] = a; items[1::2] = b"
10000 loops, best of 3: 23.4 usec per loop

The speed gain is significant. Why should I throw away useful information if
I have it? I'd even be willing to convert one arbitrary iterable to a list
to get the length information.

$ python -m timeit -s"a = [1,2,3]*100; b = [4,5,6]*100" "aa = list(a);
items=[None]*(2*len(aa)); items[::2] = aa; items[1::2] = b"
10000 loops, best of 3: 29.5 usec per loop

> Assuming that both list 
> are of the same length, then, I find the following more elegant:
> 
> list1=[1,2,3]
> list2=[4,5,6]
> 
> reduce(lambda x, y: x+y, zip(list1, list2))
> 
> of course, zip creates tuples, so you end up with a tuple, therefore if
> you need for your solution to be a list:
> list(reduce(lambda x, y: x+y, zip(list1, list2)))

I'd rather use a plain old for-loop:

>>> from itertools import izip
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> items = []
>>> for chunk in izip(a, b):
...     items.extend(chunk)
...
>>> items
[1, 4, 2, 5, 3, 6]

$ python -m timeit -s"a = [1,2,3]*100; b = [4,5,6]*100; from itertools
import izip" "items = []
> for chunk in izip(a, b): items.extend(chunk)"
1000 loops, best of 3: 242 usec per loop

$ python -m timeit -s"a = [1,2,3]*100; b = [4,5,6]*100; from itertools
import izip" "items = []; extend = items.extend
for chunk in izip(a, b): extend(chunk)"
10000 loops, best of 3: 70.9 usec per loop

> reduce(lambda x, y: x+y, list(zip(list1, list2)) )

list(zip(...)) has no effect here. Possible fixes

>>> reduce(lambda x, y: x + list(y), zip(list1, list2), [])
[1, 4, 2, 5, 3, 6]

>>> reduce(lambda x, y: x.extend(y) or x, zip(list1, list2), [])
[1, 4, 2, 5, 3, 6]

$ python -m timeit -s"a = [1,2,3]*100; b = [4,5,6]*100" "reduce(lambda x, y:
x.extend(y) or x, zip(a, b), [])"
1000 loops, best of 3: 368 usec per loop

are more complicated than elegant. Not recommended.

Peter



More information about the Python-list mailing list