11

Given a list

A = [1 2 3 4 5 6]

Is there any idiomatic (Pythonic) way to iterate over it as though it were

B = [(1, 2) (3, 4) (5, 6)]

other than indexing? That feels like a holdover from C:

for a1,a2 in [ (A[i], A[i+1]) for i in range(0, len(A), 2) ]:

I can't help but feel there should be some clever hack using itertools or slicing or something.

(Of course, two at a time is just an example; I'd like a solution that works for any n.)

Edit: related Iterate over a string 2 (or n) characters at a time in Python but even the cleanest solution (accepted, using zip) doesn't generalize well to higher n without a list comprehension and *-notation.

Community
  • 1
  • 1
Wang
  • 3,247
  • 1
  • 21
  • 33
  • I think your C holdover doesn't look that bad, but I'd write `A[i:i+1]` instead of `A[i], A[i+1]`. Easier to extend to arbitrary `n`. – Johannes Charra Mar 17 '10 at 10:42
  • 1
    Duplicate: What is the most “pythonic” way to iterate over a list in chunks? http://stackoverflow.com/questions/434287/what-is-the-most-pythonic-way-to-iterate-over-a-list-in-chunks See also http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python http://stackoverflow.com/questions/1335392/iteration-over-list-slices http://stackoverflow.com/questions/760753/iterate-over-a-python-sequence-in-multiples-of-n – jfs Mar 17 '10 at 13:46
  • The [referenced accepted answer](http://stackoverflow.com/a/1162636/923794) actually has a clean, no-copy solution, and there is no need for a list comprehension or *-notation. In the end, you'll want to loop over the data somewhere, so any loop/comprehensions/generator does not come at an extra price. Encapsulate the referenced itertools.islice based solution into a function if you like it more compact. – cfi Apr 30 '13 at 09:42

1 Answers1

12

From http://docs.python.org/library/itertools.html:

from itertools import izip_longest
def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

i = grouper(3,range(100))
i.next()
(0, 1, 2)
MattH
  • 37,273
  • 11
  • 82
  • 84
  • This may not be subjectively idiomatic or avoid list comprehensions and * notation, but it is "pythonic" enough to be in the documentation. – MattH Mar 17 '10 at 11:34
  • Ah, I knew it existed somewhere. Thank you! – Wang Mar 17 '10 at 11:34