Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over pairs in a list (circular fashion) in Python

The problem is easy, I want to iterate over each element of the list and the next one in pairs (wrapping the last one with the first).

I've thought about two unpythonic ways of doing it:

def pairs(lst):     n = len(lst)     for i in range(n):         yield lst[i],lst[(i+1)%n] 

and:

def pairs(lst):     return zip(lst,lst[1:]+[lst[:1]]) 

expected output:

>>> for i in pairs(range(10)):     print i  (0, 1) (1, 2) (2, 3) (3, 4) (4, 5) (5, 6) (6, 7) (7, 8) (8, 9) (9, 0) >>>  

any suggestions about a more pythonic way of doing this? maybe there is a predefined function out there I haven't heard about?

also a more general n-fold (with triplets, quartets, etc. instead of pairs) version could be interesting.

like image 286
fortran Avatar asked Aug 10 '09 21:08

fortran


People also ask

How do you iterate through a pair in a list Python?

combinations: A better way to iterate through a pair of values in a Python list. If you want to iterate through a pair of values in a list and the order does not matter ( (a,b) is the same as (b, a) ), use itertools. combinations instead of two for loops.

How do you iterate over a list length?

You can loop through the list items by using a while loop. Use the len() function to determine the length of the list, then start at 0 and loop your way through the list items by referring to their indexes. Remember to increase the index by 1 after each iteration.

How do you use pairs in Python?

Care has to be taken while pairing the last element with the first one to form a cyclic pair. 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.

Does Python iterate through list in order?

Yes, it should, every time, since lists are ordered. If you are iterating over a dict , the order may be different than expected. Python dicts are unordered.


2 Answers

def pairs(lst):     i = iter(lst)     first = prev = item = i.next()     for item in i:         yield prev, item         prev = item     yield item, first 

Works on any non-empty sequence, no indexing required.

like image 125
Martin v. Löwis Avatar answered Sep 27 '22 20:09

Martin v. Löwis


I've coded myself the tuple general versions, I like the first one for it's ellegant simplicity, the more I look at it, the more Pythonic it feels to me... after all, what is more Pythonic than a one liner with zip, asterisk argument expansion, list comprehensions, list slicing, list concatenation and "range"?

def ntuples(lst, n):     return zip(*[lst[i:]+lst[:i] for i in range(n)]) 

The itertools version should be efficient enough even for large lists...

from itertools import * def ntuples(lst, n):     return izip(*[chain(islice(lst,i,None), islice(lst,None,i)) for i in range(n)]) 

And a version for non-indexable sequences:

from itertools import * def ntuples(seq, n):     iseq = iter(seq)     curr = head = tuple(islice(iseq, n))     for x in chain(iseq, head):         yield curr         curr = curr[1:] + (x,) 

Anyway, thanks everybody for your suggestions! :-)

like image 42
fortran Avatar answered Sep 27 '22 22:09

fortran