3

I have a loop that is parsing lines of a text file:

for line in file:
    if line.startswith('TK'):
        for item in line.split():
            if item.startwith('ID='):
                *stuff*
            if last_iteration_of_loop
                *stuff*

I need to do a few assignments, but I can't do them until the last iteration of the second for loop. Is there a way to detect this or to know if I'm at the last item of line.split()? As a note, the items in the second for loop are strings, and their content are unknown at runtime, so I can't look for a specific string as flag to let me know I'm at the end of the list.

0

3 Answers 3

9

Just refer to the last line outside the for loop:

for line in file:
    if line.startswith('TK'):
        item = None
        for item in line.split():
            if item.startwith('ID='):
                # *stuff*

        if item is not None:
            # *stuff*

The item variable is still available outside the for loop:

>>> for i in range(5):
...     print i
... 
0
1
2
3
4
>>>  print 'last:', i
last: 4

Note that if your file is empty (no iterations through the loop) item will not be set; this is why we set item = None before the loop and test for if item is not None afterwards.

If you must have the last item that matched your test, store that in a new variable:

for line in file:
    if line.startswith('TK'):
        lastitem = None
        for item in line.split():
            if item.startwith('ID='):
                lastitem = item
                # *stuff*

        if lastitem is not None:
             # *stuff*

Demonstration of the second option:

>>> lasti = None
>>> for i in range(5):
...     if i % 2 == 0:
...         lasti = i
...
>>> lasti
4
Sign up to request clarification or add additional context in comments.

11 Comments

else to a for loop is completely pointless without a break statement in the loop.
Normally, I would agree with this approach (agreeing with @SvenMarnach). But what if the OP has to do something to 4 before printing it out? That would not work very well in this construct
I don't think it documents anything. Even idiomatic use of for/else puzzles people, but this is really confusing.
Ah, yes, I forgot about a break skipping any else clause...and so would have to tend to agree with your initial comment.
@Martijn Pieters: That's better.
|
1

Try this:

for line in file:
    if line.startswith('TK'):
        items = line.split()
        num_loops = len(items)
        for i in range len(items):
            item = items[i]
            if item.startwith('ID='):
                *stuff*
            if i==num_loops-1: # if last_iteration_of_loop
                *stuff*

Hope that helps

Comments

0

Not sure why you can't just amend outside the final loop, but you may be able to make use of this - which works with any iterator, not just those of known length...

not extensively tested and possibly not efficient

from itertools import tee, izip_longest, count

def something(iterable):
    sentinel = object()
    next_count = count(1)

    iterable = iter(iterable)
    try:
        first = next(iterable)
    except StopIteration:
        yield sentinel, 'E', 0 # empty

    yield first, 'F', next(next_count) # first

    fst, snd = tee(iterable)
    next(snd)
    for one, two in izip_longest(fst, snd, fillvalue=sentinel):
        yield one, 'L' if two is sentinel else 'B', next(next_count) # 'L' = last, 'B' = body

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.