Pairs from single list
Question: Often enough, I've found the need to process a list by pairs. I was wondering
which would be the pythonic and efficient way to do it, and found this on
Google:

    
    
    pairs = zip(t[::2], t[1::2])
    

I thought that was pythonic enough, but after a recent discussion involving
[idioms versus efficiency](http://stackoverflow.com/questions/4619367/avoid-
object-aliasing-in-python/4619575#4619575), I decided to do some tests:

    
    
    import time
    from itertools import islice, izip
    
    def pairs_1(t):
        return zip(t[::2], t[1::2]) 
    
    def pairs_2(t):
        return izip(t[::2], t[1::2]) 
    
    def pairs_3(t):
        return izip(islice(t,None,None,2), islice(t,1,None,2))
    
    A = range(10000)
    B = xrange(len(A))
    
    def pairs_4(t):
        # ignore value of t!
        t = B
        return izip(islice(t,None,None,2), islice(t,1,None,2))
    
    for f in pairs_1, pairs_2, pairs_3, pairs_4:
        # time the pairing
        s = time.time()
        for i in range(1000):
            p = f(A)
        t1 = time.time() - s
    
        # time using the pairs
        s = time.time()
        for i in range(1000):
            p = f(A)
            for a, b in p:
                pass
        t2 = time.time() - s
        print t1, t2, t2-t1
    

These were the results on my computer:

    
    
    1.48668909073 2.63187503815 1.14518594742
    0.105381965637 1.35109519958 1.24571323395
    0.00257992744446 1.46182489395 1.45924496651
    0.00251388549805 1.70076990128 1.69825601578
    

If I'm interpreting them correctly, that should mean that the implementation
of lists, list indexing, and list slicing in Python is very efficient. It's a
result both comforting and unexpected.

**Is there another, "better" way of traversing a list in pairs?**

Note that if the list has an odd number of elements then the last one will not
be in any of the pairs.

**Which would be the right way to ensure that all elements are included?**

I added these two suggestions from the answers to the tests:

    
    
    def pairwise(t):
        it = iter(t)
        return izip(it, it)
    
    def chunkwise(t, size=2):
        it = iter(t)
        return izip(*[it]*size)
    

These are the results:

    
    
    0.00159502029419 1.25745987892 1.25586485863
    0.00222492218018 1.23795199394 1.23572707176
    

## Results so far

Most pythonic and very efficient:

    
    
    pairs = izip(t[::2], t[1::2])
    

Most efficient and very pythonic:

    
    
    pairs = izip(*[iter(t)]*2)
    

It took me a moment to grok that the first answer uses two iterators while the
second uses a single one.

To deal with sequences with an odd number of elements, the suggestion has been
to augment the original sequence adding one element (`None`) that gets paired
with the previous last element, something that can be achieved with
`itertools.izip_longest()`.

## Finally

Note that, in Python 3.x, `zip()` behaves as `itertools.izip()`, and
`itertools.izip()` is gone.


Answer: I'd say that your initial solution `pairs = zip(t[::2], t[1::2])` is the best
one because it is easiest to read (and in Python 3, `zip` automatically
returns an iterator instead of a list).

To ensure that all elements are included, you could simply extend the list by
`None`.

Then, if the list has an odd number of elements, the last pair will be `(item,
None)`.

    
    
    >>> t = [1,2,3,4,5]
    >>> t.append(None)
    >>> zip(t[::2], t[1::2])
    [(1, 2), (3, 4), (5, None)]
    >>> t = [1,2,3,4,5,6]
    >>> t.append(None)
    >>> zip(t[::2], t[1::2])
    [(1, 2), (3, 4), (5, 6)]
    

