I pondered on the question of what is the Pythonic way, and came to the conclusion that if you do not need a sequence, then accept any iterator would be the Pythonic one. Martijn's xrange method is not the most pythonic in this sense, and indeed the Martijn's grouper method
result = [ i[:2] + j[:2] for i, j in izip(*[iter(l)] * 2) ]
is the most pythonic in that it accepts any kind of iterable.
The [iter(l)] * 2
makes a 2-sized list with the same iterator in both elements. The reason why this is faster than my attempt with next
above, though I didn't think so before, is that the call to next()
is costly (all function calls and attribute/name resolves are slow on CPython relative to use of inline operators and construction of tuples).
This is the quick obvious solution, that I find the most Pythonic with strictly lists:
l = [('a1', 'a2', 'a3', 'a4'), ('b1', 'b2', 'b3', 'b4'), ('c1', 'c2', 'c3', 'c4'), ('d1', 'd2', 'd3', 'd4')]
y = [ i[:2] + j[:2] for i, j in zip(l[::2], l[1::2]) ]
print y
which prints
[('a1', 'a2', 'b1', 'b2'), ('c1', 'c2', 'd1', 'd2')]
However it is not the most efficient, as zip
and the slices will create temporary lists on Python 2, thus to speed this up, one can use the itertools.izip
with islice
to make a generative solution.
But, actually one can abuse an iterator here to make quite efficient code, albeit not very Pythonic
i = iter(l)
n = i.next
result = [ j[:2] + n()[:2] for j in i ]
print result
prints
[('a1', 'a2', 'b1', 'b2'), ('c1', 'c2', 'd1', 'd2')]
The for
in list comprehension implicitly calls next()
on the iterator i
and assigns the result to j
; within the list comprehension body we explicitly advance the same iterator to get the next tuple. Then with tuple slicing we take the 2 first elements of the even numbered tuple (0-based) and concatenate the 2 first elements of the next tuple to it. This code however will result in StopIteration
exception if the number of elements in the original list is not even, unlike the slice'n'zip solutions which would just silently discard the last odd tuple.