tags:

views:

798

answers:

5

How can I do thing like this 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]
    }
}
+1  A: 

This should do the trick.

foo = somevalue
previous = None
next = None
for index, obj in enumerate(objects):
    if obj == foo:
        # TODO Bounds-checking
        previous = objects[index - 1]
        next = objects[index + 1]

Here's the docs on the enumerate function.

Hank Gay
A: 

You could just use index on the list to find where somevalue is and then get the previous and next as needed:


def find_prev_next(elem, elements):
    previous, next = None, None
    index = elements.index(elem)
    if index > 0:
        previous = elements[index -1]
    if index < (len(elements)-1):
        next = elements[index +1]
    return previous, next


foo = 'three'
list = ['one','two','three', 'four', 'five']

previous, next = find_prev_next(foo, list)

print previous # should print 'two'
print next # should print 'four'


John Montgomery
A: 

using conditional expressions for conciseness for python >= 2.5

def prenext(l,v) : 
   i=l.index(v)
   return l[i-1] if i>0 else None,l[i+1] if i<len(l)-1 else None


# example
x=range(10)
prenext(x,3)
>>> (2,4)
prenext(x,0)
>>> (None,2)
prenext(x,9)
>>> (8,None)
makapuf
+14  A: 

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, next in previous_and_next(mylist):
    print "Item is now", item, "next is", next, "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, 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.

nosklo
Nice solution. Like the unpacking.
Skurmedel
The solution calls for an explanation of tee, islice, chain, and izip..
Lakshman Prasad
@becomingGuru: it isn't necessary to turn SO into a mirror of the Python reference docs. All these functions are very nicely explained (with examples) in the official documentation
Eli Bendersky
@becomingGuru: Added a link to the documentation.
nosklo
+1  A: 

Here's a version using generators with no boundary errors:

def trios(input):
    input = iter(input) # make sure input is an iterator
    try:
        prev, current = input.next(), input.next()
    except StopIteration:
        return
    for next in input:
        yield prev, current, next
        prev, current = current, next

def find_prev_next(objects, foo):
    prev, next = 0, 0
    for temp_prev, current, temp_next in trios(objects):
        if current == foo:
            prev, next = temp_prev, temp_next
    return prev, next

print find_prev_next(range(10), 1)
print find_prev_next(range(10), 0)
print find_prev_next(range(10), 10)
print find_prev_next(range(0), 10)
print find_prev_next(range(1), 10)
print find_prev_next(range(2), 10)

Please notice that the boundary behavior is that we never look for "foo" in the first or last element, unlike your code. Again, the boundary semantics are strange...and are hard to fathom from your code :)

moshez