Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop that also accesses previous and next values

How can I iterate over a list of objects, accessing the previous, current, and next items? Like this C/C++ code, in Python?

foo = somevalue; previous = next = 0;  for (i=1; i<objects.length(); i++) {     if (objects[i]==foo) {         previous = objects[i-1];         next = objects[i+1];     } } 
like image 814
dir01 Avatar asked Jun 18 '09 10:06

dir01


People also ask

How do you access the next element in a for loop?

Use enumerate() function to access the next item in a list in python for a loop. The for loop allows to access the variables next to the current value of the indexing variable in the list.


2 Answers

Solutions until now only deal with lists, and most are copying the list. In my experience a lot of times that isn't possible.

Also, they don't deal with the fact that you can have repeated elements in the list.

The title of your question says "Previous and next values inside a loop", but if you run most answers here inside a loop, you'll end up iterating over the entire list again on each element to find it.

So I've just created a function that. using the itertools module, splits and slices the iterable, and generates tuples with the previous and next elements together. Not exactly what your code does, but it is worth taking a look, because it can probably solve your problem.

from itertools import tee, islice, chain, izip  def previous_and_next(some_iterable):     prevs, items, nexts = tee(some_iterable, 3)     prevs = chain([None], prevs)     nexts = chain(islice(nexts, 1, None), [None])     return izip(prevs, items, nexts) 

Then use it in a loop, and you'll have previous and next items in it:

mylist = ['banana', 'orange', 'apple', 'kiwi', 'tomato']  for previous, item, nxt in previous_and_next(mylist):     print "Item is now", item, "next is", nxt, "previous is", previous 

The results:

Item is now banana next is orange previous is None Item is now orange next is apple previous is banana Item is now apple next is kiwi previous is orange Item is now kiwi next is tomato previous is apple Item is now tomato next is None previous is kiwi 

It'll work with any size list (because it doesn't copy the list), and with any iterable (files, sets, etc). This way you can just iterate over the sequence, and have the previous and next items available inside the loop. No need to search again for the item in the sequence.

A short explanation of the code:

  • tee is used to efficiently create 3 independent iterators over the input sequence
  • chain links two sequences into one; it's used here to append a single-element sequence [None] to prevs
  • islice is used to make a sequence of all elements except the first, then chain is used to append a None to its end
  • There are now 3 independent sequences based on some_iterable that look like:
    • prevs: None, A, B, C, D, E
    • items: A, B, C, D, E
    • nexts: B, C, D, E, None
  • finally izip is used to change 3 sequences into one sequence of triplets.

Note that izip stops when any input sequence gets exhausted, so the last element of prevs will be ignored, which is correct - there's no such element that the last element would be its prev. We could try to strip off the last elements from prevs but izip's behaviour makes that redundant

Also note that tee, izip, islice and chain come from the itertools module; they operate on their input sequences on-the-fly (lazily), which makes them efficient and doesn't introduce the need of having the whole sequence in memory at once at any time.

In python 3, it will show an error while importing izip,you can use zip instead of izip. No need to import zip, it is predefined in python 3 - source

like image 122
nosklo Avatar answered Oct 10 '22 09:10

nosklo


This should do the trick.

foo = somevalue previous = next_ = None l = len(objects) for index, obj in enumerate(objects):     if obj == foo:         if index > 0:             previous = objects[index - 1]         if index < (l - 1):             next_ = objects[index + 1] 

Here's the docs on the enumerate function.

like image 37
Hank Gay Avatar answered Oct 10 '22 10:10

Hank Gay