Pythonic approach to zipping items in a list

Question:

Say I want to iterate through a list. Each time I iterate I want to compute something using both the current and next terms. I could do something like

mylist = [1, 2, 3, 4]
for i in range(len(mylist)):
    try:
        compute(mylist[i], mylist[i+1])
    except IndexError:
        compute(mylist[i])

I could also do

mylist = [1, 2, 3, 4]
for num in mylist:
    try:
        compute(num, mylist[mylist.index(num)+1])
    except IndexError:
        compute(num)

Neither of these seems particularly good. Is there a more pythonic approach to doing this?

Asked By: Bruno

||

Answers:

A functional style that doesn’t use itertools might look something like:

for t in zip(mylist, mylist[1:]):
    compute(*t)

If performance is tantamount you can prevent the creation of the intermeida list during zip by using itertools.izip.

To cover the special case as shown in the question, use:

for t in zip(mylist, mylist[1:]) + [(mylist[-1],)]
    compute(*t)
Answered By: cmh

You can use built-in function enumerate:

mylist = [1, 2, 3, 4]
for i, num in enumerate(mylist):
    try:
        compute(num, mylist[i+1])
    except IndexError:
        compute(num)

But choosing between your two implementations is rather easy – second is not only far slower (O(n^2)), but also has weird semantics for repeating elements.

Answered By: zch

To cover your special case at the end, you need:

for t in zip(mylist, mylist[1:]) + [(mylist[-1],)]
    compute(*t)
Answered By: Eric

There are three ways to do that (although I would probably prefer first one, unless your conditions are different):

  1. Use itertools.izip() – it will be efficient and Pythonic:

    for item1, item2 in itertools.izip(my_list, my_list[1:]):
        # do something...
    
  2. Use enumerate():

    for index, item in enumerate(my_list):
        # do something...
    
  3. Store previous row in a variable (the example assumes there is no None in your list):

    previous = None
    for item in my_list:
        if previous is None:
            previous = item
            continue
        # do something...
    
Answered By: Tadeck
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.