305

I want to loop through a Python list and process 2 list items at a time. Something like this in another language:

for(int i = 0; i < list.length(); i+=2)
{
   // do something with list[i] and list[i + 1]
}

What's the best way to accomplish this?

martineau
  • 119,623
  • 25
  • 170
  • 301
froadie
  • 79,995
  • 75
  • 166
  • 235

7 Answers7

483

You can use a range with a step size of 2:

Python 2

for i in xrange(0,10,2):
  print(i)

Python 3

for i in range(0,10,2):
  print(i)

Note: Use xrange in Python 2 instead of range because it is more efficient as it generates an iterable object, and not the whole list.

Olivia Stork
  • 4,660
  • 5
  • 27
  • 40
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
139

You can also use this syntax (L[start:stop:step]):

mylist = [1,2,3,4,5,6,7,8,9,10]
for i in mylist[::2]:
    print i,
# prints 1 3 5 7 9

for i in mylist[1::2]:
    print i,
# prints 2 4 6 8 10

Where the first digit is the starting index (defaults to beginning of list or 0), 2nd is ending slice index (defaults to end of list), and the third digit is the offset or step.

jathanism
  • 33,067
  • 9
  • 68
  • 86
  • 12
    This will work very well, as long as the `list` isn't huge. If the `list` _is_ huge, you're making a copy of it when you use the slicing syntax... – Chinmay Kanchi Jun 07 '10 at 14:29
  • 1
    Your answer is good for me when using parameter: `range(my_param)[::2]` – Eli Mar 01 '16 at 11:27
  • 1
    I like that the range is implied with this. You don't have get the length of the list to compare that against a variable. – BuvinJ Jul 11 '16 at 13:21
  • 1
    This is the best answer for me, in my preset list every second item is info for the previous(main items). I need to loop only through the main items. This answer realy does it. – Avraham Zhurba Oct 24 '18 at 18:51
83

The simplest in my opinion is just this:

it = iter([1,2,3,4,5,6])
for x, y in zip(it, it):
    print x, y

Out: 1 2
     3 4
     5 6

No extra imports or anything. And very elegant, in my opinion.

Suzana
  • 4,251
  • 2
  • 28
  • 52
carl
  • 49,756
  • 17
  • 74
  • 82
46

If you're using Python 2.6 or newer you can use the grouper recipe from the itertools module:

from itertools import izip_longest

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

Call like this:

for item1, item2 in grouper(2, l):
    # Do something with item1 and item2

Note that in Python 3.x you should use zip_longest instead of izip_longest.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • +1 This is the method the documentation itself suggests. – Brian Jun 07 '10 at 14:37
  • just in case you are wondering how it works, consider all iterators in args advance together so that izip will always take next element when invoking next() on its arguments – user110954 Oct 18 '16 at 17:50
7
nums = range(10)
for i in range(0, len(nums)-1, 2):
    print nums[i]

Kinda dirty but it works.

Ishpeck
  • 2,001
  • 1
  • 19
  • 21
  • Considering that `range`/`xrange` have built in support for changing the increment value, this solution seems kind of silly. – Brian Jun 07 '10 at 14:33
  • 2
    Umm, that's what the the last parameter to `range` is doing... – Michael Mior Jun 07 '10 at 18:36
  • It's presumed that nums is a sequence we have no control over. The demonstration really begins subsequent to the first line where I assign `nums` a value. – Ishpeck Jun 07 '10 at 23:16
3

This might not be as fast as the izip_longest solution (I didn't actually test it), but it will work with python < 2.6 (izip_longest was added in 2.6):

from itertools import imap

def grouper(n, iterable):
    "grouper(3, 'ABCDEFG') --> ('A,'B','C'), ('D','E','F'), ('G',None,None)"
    args = [iter(iterable)] * n

    return imap(None, *args)

If you need to go earlier than 2.3, you can substitute the built-in map for imap. The disadvantage is that it provides no ability to customize the fill value.

PascalVKooten
  • 20,643
  • 17
  • 103
  • 160
lambacck
  • 9,768
  • 3
  • 34
  • 46
-2

If you have control over the structure of the list, the most pythonic thing to do would probably be to change it from:

l=[1,2,3,4]

to:

l=[(1,2),(3,4)]

Then, your loop would be:

for i,j in l:
    print i, j
Jorenko
  • 2,594
  • 2
  • 21
  • 26
  • 8
    It's a property being read in from an external file. I can't control the list and I actually am trying to change it from `l=[1,2,3,4]` to `l=[(1,2),(3,4)]` which is why I'm asking the question – froadie Jun 07 '10 at 14:10