0

It's a common programming task to loop iteration while not receiving next item. For example:

for sLine in oFile :
  if ... some logic ... :
    sLine = oFile.next()
    ... some more logic ...
    # at this point i want to continue iteration but without
    # getting next item from oFile. How can this be done in python?
1
  • -1: This is baffling. Perhaps you want a "GOTO"? Or perhaps you need to define some functions that you can reuse to avoid this contrived looping?
    – S.Lott
    Commented Apr 1, 2009 at 14:55

8 Answers 8

3

I first thought you wanted the continue keyword, but that would of course get you the next line of input.

I think I'm stumped. When looping over the lines of a file, what exactly should happen if you continued the loop without getting a new line?

Do you want to inspect the line again? If so, I suggest adding an inner loop that runs until you're "done" with the input line, which you can then break out of, or use maybe the while-condition and a flag variable to terminate.

1
  • +1: I was rather stumped too by how someone could expect a file iterator to go on to the next iteration without reading the next line :-) Commented Apr 1, 2009 at 14:47
2

Simply create an iterator of your own that lets you push data back on the front of the stream so that you can give the loop a line that you want to see over again:

next_lines = []
def prependIterator(i):
    while True:
        if next_lines:
            yield(next_lines.pop())
        else:
            yield(i.next())

for sLine in prependIterator(oFile):
    if ... some logic ... :
        sLine = oFile.next()
        ... some more logic ...
        # put the line back so that it gets read
        # again as we head back up to the "for
        # statement
        next_lines.append(sLine)

If the prepend_list is never touched, then the prependIterator behaves exactly like whatever iterator it is passed: the if statement inside will always get False and it will just yield up everything in the iterator it has been passed. But if items are placed on the prepend_list at any point during the iteration, then those will be yielded first instead before it returns back to reading from the main iterator.

1

What you need is a simple, deterministic finite state machine. Something like this...

state = 1
for sLine in oFile:
   if state == 1:
      if ... some logic ... :
         state = 2
   elif state == 2:
      if ... some logic ... :
         state = 1
3
  • no other ways in python? state machine is a good choice, but needs a bit more code :(
    – grigoryvp
    Commented Apr 1, 2009 at 14:51
  • I may be missing something. How does this help the user put an object back on the front of his iterable for re-consumption? Commented Apr 2, 2009 at 12:25
  • Putting an object back isn't the problem. Putting an object back is a solution to a problem. It's just not a good solution. If it was, then programming languages would provide a way to handle it easily. From a CE perspective, FSM is a better solution.
    – Glenn
    Commented Apr 3, 2009 at 19:47
0

Ugly. Wrap the body in another loop.

for sLine in oFile :
  while 1:
    if ... some logic ... :
      sLine = oFile.next()
      ... some more logic ...
      continue
    ... some more logic ...
    break

A little better:

class pushback_iter(object):
    def __init__(self,iterable):
        self.iterator = iter(iterable)
        self.buffer = []
    def next(self):
        if self.buffer:
            return self.buffer.pop()
        else:
            return self.iterator.next()
    def __iter__(self):
        return self
    def push(self,item):
        self.buffer.append(item)

it_file = pushback_iter(file)
for sLine in it_file:
    if ... some logic ... :
        sLine = it_file.next()
        ... some more logic ...
        it_file.push(sLine)
        continue
    ... some more logic ...

Unfortunately no simple way of referencing the current iterator.

1
  • This looks like a decent solution — not as compact as the suggestion I made about using a generator, but, still, something that uses the same logic, and one of the very few answers here that actually solves the questioner's problem. Commented Apr 1, 2009 at 22:09
0

Instead of looping through the file line by line, you can do a file.readlines() into a list. Then loop through the list (which allows you to look at the next item if you want). Example:

list = oFile.readlines()
for i in range(len(list))
    #your stuff
    list[i] #current line
    list[i-1] #previous line
    list[i+1] #next line

you can go to the previous or next line by simply using [i-1] or [i+1]. You just need to make sure that no matter what, i does not go out of range.

4
  • is it a way to move one element backwards while iterating list via for in in list ? In text parsing it's a common task if you accumulate lines until you find a line that NOT fits and you need to check this line again
    – grigoryvp
    Commented Apr 1, 2009 at 14:44
  • @eye of hell: if you have a particular use case in mind, please update the question with the description of what you are trying to accomplish in that use case. Commented Apr 1, 2009 at 14:49
  • note that even if you use this method i will still be reset to the next number, so you'd also need to remove the next entry from the list (which is expensive). Commented Apr 1, 2009 at 20:19
  • @eye of hell: if instead of using a for loop you use a while loop and manually increment or decrement the index as you need to.
    – neil
    Commented Mar 8, 2011 at 11:48
-1

You just need to create a variable out of your iterator, and then manipulate that:

% cat /tmp/alt-lines.py 
#! /usr/bin/python -tt

import sys

lines = iter(open(sys.argv[1]))
for line in lines:
    print line,
    lines.next()

% cat /tmp/test
1
2
3
4
% /tmp/alt-lines.py /tmp/test
1
3

...note that in this case we unconditionally do lines.next() so the above fails for files with odd lines, but I assume that isn't going to be the case for you (and adding the error checking is fairly trivial -- just catch and throw away StopIteration on the manual .next()).

-1

You can assign your iterator to an variable then use the .next get te next one.

iter = oFile.xreadlines() # is this the correct iterator you want?
try:
  sLine = iter.next()
  while True:
    if ... some logic ... :
      sLine = iter.next()
      ... some more logic ...
      continue
    sLine = iter.next()
except StopIterator:
  pass
1
  • readlines() isn't an iterator. It returns a list, and lists don't have a 'next()' property. Commented Apr 1, 2009 at 15:06
-2

jle's approach should work, though you might as well use enumerate():

for linenr, line in enumerate(oFile):
    # your stuff

Not the answer you're looking for? Browse other questions tagged or ask your own question.