22

Possible Duplicates:
Python - Previous and next values inside a loop
python for loop, how to find next value(object)?

I've got a list that contains a lot of elements, I iterate over the list using a for loop. For example:

li = [2, 31, 321, 41, 3423, 4, 234, 24, 32, 42, 3, 24, 31, 123]

for i in li:
    print(i)

But I want to get the element before i. How can I achieve that?

Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
user469652
  • 44,657
  • 57
  • 123
  • 163
  • [some](http://stackoverflow.com/questions/323750/how-to-access-previous-next-element-while-for-looping) [other](http://stackoverflow.com/questions/1281752/accessing-elements-with-offsets-in-pythons-for-in-loops) [links](http://stackoverflow.com/questions/522563/accessing-the-index-in-python-for-loops) – aaronasterling Oct 23 '10 at 05:33

7 Answers7

38

You can use zip:

for previous, current in zip(li, li[1:]):
    print(previous, current)

or, if you need to do something a little fancier, because creating a list or taking a slice of li would be inefficient, use the pairwise recipe from itertools

import itertools

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = itertools.tee(iterable)
    next(b, None)
    return zip(a, b)

for a, b in pairwise(li):
    print(a, b)
Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
SingleNegationElimination
  • 144,899
  • 31
  • 254
  • 294
  • 2
    +1 for the itertools answer, not the first. The first is fine if the list is small, but if the list is really large, creating a copy would be inefficient. – snapshoe Oct 23 '10 at 15:58
23

Normally, you use enumerate() or range() to go through the elements. Here's an alternative using zip()

>>> li = [2, 31, 321, 41, 3423, 4, 234, 24, 32, 42, 3, 24, 31, 123]
>>> list(zip(li[1:], li))
[(31, 2), (321, 31), (41, 321), (3423, 41), (4, 3423), (234, 4), (24, 234), (32, 24), (42, 32), (3, 42), (24, 3), (31, 24), (123, 31)]

the 2nd element of each tuple is the previous element of the list.

Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
ghostdog74
  • 307,646
  • 55
  • 250
  • 337
  • 3
    Yes, this does work, but if your list is really large, do you really want to take the performance hit of creating a second really large list (with `li[1:]`)? – snapshoe Oct 23 '10 at 15:55
  • I already said its an alternative. Of course if the list is REALLY large, then don't use this method. simple as that. – ghostdog74 Oct 23 '10 at 16:21
21

Just keep track of index using enumerate and get the previous item by index

li = list(range(10))

for i, item in enumerate(li):
    if i > 0:
        print(item, li[i-1])

print("or...")

for i in range(1, len(li)):
    print li[i], li[i-1]

Output:

1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8
or...
1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8

Another alternative is to remember the last item, e.g.

last_item = None
for item in li:
    print(last_item, item)
    last_item = item
Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
Anurag Uniyal
  • 81,711
  • 39
  • 167
  • 215
7
j = None
for i in li:
    print(j)
    j = i
Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
kindall
  • 168,929
  • 32
  • 262
  • 294
3

An option using the itertools recipe from here:

from itertools import tee
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

for i, j in pairwise(li):
    print(i, j)
Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
Muhammad Alkarouri
  • 22,738
  • 18
  • 63
  • 99
1

Use a loop counter as an index. (Be sure to start at 1 so you stay in range.)

for i in range(1, len(li)):
  print(li[i], li[i-1])
Boris Verkhovskiy
  • 10,733
  • 7
  • 77
  • 79
JoshD
  • 12,052
  • 2
  • 40
  • 52
-3
li = [2,31,321,41,3423,4,234,24,32,42,3,24,,31,123]

counter = 0
for l in li:
    print l
    print li[counter-1] #Will return last element in list during first iteration as martineau points out.
    counter+=1
jMyles
  • 11,224
  • 6
  • 41
  • 56
  • You're wrong about an exception being raised the first iteration. `alist[-1]` is the last element of the list. Doesn't sound like you tried running it yourself -- not worth a downvote, though. – martineau Oct 23 '10 at 12:07
  • Thank you - I learned something today. :-) – jMyles Oct 23 '10 at 19:11