Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pairs from single list

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, 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.

like image 642
Apalala Avatar asked Jan 07 '11 17:01

Apalala


People also ask

How do you create a pair from one list in Python?

zip function can be used to extract pairs over the list and slicing can be used to successively pair the current element with the next one for the efficient pairing.

What is pair () in Python?

Pairs in Python. Page 1. Pairs in Python. To enable us to implement the concrete level of our data abstraction, Python provides a compound structure called a tuple, which can be constructed by separating values by commas. Although not strictly required, parentheses almost always surround tuples.

What is list pair?

A list is a combination of pairs that creates a linked list. More precisely, a list is either the empty list null, or it is a pair whose first element is a list element and whose second element is a list.


1 Answers

My favorite way to do it:

def pairwise(t):     it = iter(t)     return zip(it,it)  # for "pairs" of any length def chunkwise(t, size=2):     it = iter(t)     return zip(*[it]*size) 

When you want to pair all elements you obviously might need a fillvalue:

from itertools import izip_longest def blockwise(t, size=2, fillvalue=None):     it = iter(t)     return izip_longest(*[it]*size, fillvalue=fillvalue) 

With Python 3, itertools.izip is now simply zip .. to work with an older Python, use

from itertools import izip as zip 
like image 178
Jochen Ritzel Avatar answered Sep 29 '22 11:09

Jochen Ritzel