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