pythonlist

Iterating over every two elements in a list


How do I make a for loop or a list comprehension so that every iteration gives me two elements?

l = [1,2,3,4,5,6]

for i,k in ???:
    print str(i), '+', str(k), '=', str(i+k)

Output:

1+2=3
3+4=7
5+6=11

Solution

  • Starting with Python 3.12, you can use the batched() function provided by the itertools module:

    from itertools import batched
    
    for x, y in batched(l, n=2):
        print("%d + %d = %d" % (x, y, x + y))
    

    Otherwise, you need a pairwise() (or grouped()) implementation.

    def pairwise(iterable):
        "s -> (s0, s1), (s2, s3), (s4, s5), ..."
        a = iter(iterable)
        return zip(a, a)
    
    for x, y in pairwise(l):
       print("%d + %d = %d" % (x, y, x + y))
    

    Or, more generally:

    def grouped(iterable, n):
        "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
        return zip(*[iter(iterable)]*n)
    
    for x, y in grouped(l, 2):
       print("%d + %d = %d" % (x, y, x + y))
    

    In Python 2, you should import izip as a replacement for Python 3's built-in zip() function.

    All credit to martineau for his answer to my question, I have found this to be very efficient as it only iterates once over the list and does not create any unnecessary lists in the process.

    N.B: This should not be confused with the pairwise recipe in Python's own itertools documentation, which yields s -> (s0, s1), (s1, s2), (s2, s3), ..., as pointed out by @lazyr in the comments.

    Little addition for those who would like to do type checking with mypy on Python 3:

    from typing import Iterable, Tuple, TypeVar
    
    T = TypeVar("T")
    
    def grouped(iterable: Iterable[T], n=2) -> Iterable[Tuple[T, ...]]:
        """s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), ..."""
        return zip(*[iter(iterable)] * n)