tags:

views:

264

answers:

5

This might be a really dumb question, however I've looked around online, etc. And have not seen a solid answer.

Is there a simple way to do something like this?

lines = open('something.txt', 'r').readlines()
for line in lines:
    if line == '!':
        # force iteration forward twice
        line.next().next()
    <etc>

It's easy to do in C++; just increment the iterator an extra time. Is there an easy way to do that in Python?

I would just like to point, out the main purpose of this question is not about "reading files and such" and skipping things. I was more looking for C++ iterator style iteration. Also the new title is kinda dumb, and i dont really think it reflects the nature of my question.

+1  A: 

Not very compact:

skip = False
for line in open('something.txt'):
  if skip:
    skip = False
    continue

  if line.strip() == '!':
    skip = True
    continue
Harriv
line won't ever be equal to `'!'` unless you strip the newline character(s) from the end first.
tgray
Fixed by adding .strip()
Harriv
A: 

You could use recursion

input = iter( open('something.txt') )
def myFunc( item ):
    val = iter.next()
    if( val == '!' ):
        item.next()
        return myFunc( item )
    #continue on with looping logic

Editted post contained the following which actually didn't answer your question:

Have you tried

[line for line in open('something.txt') if line != '!']

to produce a new list? Or even better

filter( lambda line: line != '!', open('something.txt') )
wheaties
Why not use a generator expression rather than a list comprehension? Just replace the `[` and `]` with `(` and `)` and it will still be iterable, but won't duplicate the list—important if the file is huge.
Samir Talwar
The recursion version will break on files with more than 1000 lines (Python implementation dependent).
ebo
Unless the evil trampoline is used: http://aspn.activestate.com/ASPN/Mail/Message/python-tutor/2302231
RaphaelSP
wow, that is evil and I need to play around with it. Thanks.
wheaties
@Downvoter: this answer does address the problem... Would you mind to explain ?
RaphaelSP
+8  A: 

Try:

lines = iter(open('something.txt', 'r'))
for val in lines:
    if val == "!":
        lines.next()
        continue
    <etc>

You may want to catch StopIteration somewhere. It'll occur if the iterator is finished.

ebo
You can use `next(lines, None)` to suppress the `StopIteration` exception. (Requires Python 2.6)
interjay
any chance for bidirectional iteration?
UberJumper
Not with default iterators. You can however make your own iterator style classes by overriding the correct functions.
ebo
this solution is not as clean as the one with the **`with`** statement because you should really be clean about the file and close it. you get this for free with **`with`**.
wescpy
+3  A: 

The file.readlines method returns a list of strings, and iterating over a list will not let you modify the iteration in the body of the loop. However if you call iter on the list first then you will get an iterator that you can modify in the loop body:

lines = open('something.txt', 'r').readlines()
line_iter = iter(lines)
for line in line_iter:
    if line == '!':
        # force iteration forward twice
        line_iter.next()
        line_iter.next()
    <etc>

As ebo points out the file object itself acts as an iterator, so you can get the same effect by not calling readlines and leaving out the call to iter.

Dave Kirby
+4  A: 

This is short, pythonic, and works:

with open('something.txt', 'r') as f: # or simply f = open('something.txt', 'r')
    nobang = (line for line in f if line != '!\n')
    for line in nobang:
        #...

Edit:

As many observed, this is not the solution yet. The best I can think of is a combination of what is already on this page:

with open('something.txt', 'r') as f:
    for line in f:
        if line == '!\n':
            next(f,None) # consume next line
            continue # skip this line
        # ...
Olivier
this is p3k syntax, right?
Dingle
This doesn't skip the next line.
interjay
@Dingle: No, just 2.6 or later.
Kimmo Puputti
This is by far the most elegant one up to now, +1!
Morlock
@interjay: true! :-)
Olivier
@Morlock: Except that it doesn't do what the original poster asked for -- namely, it doesn't skip the line *following* the line that has a '!'.
Edward Loper
@Edward Loper well, indeed, that's quite an overlook of me ;) Still very instructive as to few people seem to use generators like this.
Morlock
u can use this in Python 3.x as well as Python 2.5 and newer. as described above, it's defaulted on in 2.6+ but for 2.5.x, you need to issue `from __future__ import with_statement`
wescpy