Accessing next/prev element while for looping

Bengt Richter bokr at oz.net
Sun Dec 18 08:23:12 EST 2005


On Sun, 18 Dec 2005 04:23:21 -0700, Joseph Garvin <k04jg02 at kzoo.edu> wrote:

>When I first came to Python I did a lot of C style loops like this:
>
>for i in range(len(myarray)):
>    print myarray[i]
>
>Obviously the more pythonic way is:
>
>for i in my array:
>    print i
>
>The python way is much more succinct. But a lot of times I'll be looping 
>through something, and if a certain condition is met, need to access the 
>previous or the next element in the array before continuing iterating. I 
>don't see any elegant way to do this other than to switch back to the C 
>style loop and refer to myarray[i-1] and myarray[i+1], which seems 
>incredibly silly given that python lists under the hood are linked 
>lists, presumably having previous/next pointers although I haven't 
>looked at the interpeter source.
>
>I could also enumerate:
>
>for i, j in enumerate(myarray):
>    print myarray[i], j # Prints each element twice
>
>And this way I can keep referring to j instead of myarray[i], but I'm 
>still forced to use myarray[i-1] and myarray[i+1] to refer to the 
>previous and next elements. Being able to do j.prev, j.next seems more 
>intuitive.
>
>Is there some other builtin somewhere that provides better functionality 
>that I'm missing?
I don't know of a builtin, but you could make an iterator that gives you
your sequence as (prev, curr, next) item tuples, where curr is the normal
single item in for curr in my_array: ... e.g.,

 >>> def pcniter(seq, NULL=NotImplemented):
 ...     seqiter = iter(seq)
 ...     prev = curr = NULL
 ...     try: next = seqiter.next()
 ...     except StopIteration: return
 ...     for item in seqiter:
 ...         prev, curr, next = curr, next, item
 ...         yield prev, curr, next
 ...     yield curr, next, NULL
 ...
 >>> for prev, curr, next in pcniter('abcdef', '\x00'): print '%8r'*3 %( prev, curr, next)
 ...
   '\x00'     'a'     'b'
      'a'     'b'     'c'
      'b'     'c'     'd'
      'c'     'd'     'e'
      'd'     'e'     'f'
      'e'     'f'  '\x00'
 >>> for prev, curr, next in pcniter(xrange(4), 'NULL' ): print '%8r'*3 %( prev, curr, next)
 ...
   'NULL'       0       1
        0       1       2
        1       2       3
        2       3  'NULL'

If you want to assign back into myarray[i-1] etc, you'd still need to enumerate, but you could
combine with the above it was useful.

Regards,
Bengt Richter



More information about the Python-list mailing list