1

I have the following text file (file.txt):

1
2 inside
3
4 outside
5
6

and when I run the following code:

with open("file.txt") as f:
    for value in f:
        print("outer loop (value):         ",value,end="")
        if "inside" in value:
            lstItem = []
            lstItem.append(value)
            for i,value in enumerate(f):
                print("inner loop (index:value): ",i,value,end="")
                lstItem.append(value)
                if "outside" in value:
                    break
            print(),print(lstItem),print()

this is my output:

outer loop (value):          1
outer loop (value):          2 inside
inner loop (index:value):  0 3
inner loop (index:value):  1 4 outside

['2 inside\n', '3\n', '4 outside\n']

outer loop (value):          5
outer loop (value):          6

So I get why "2 inside" is not being included in the nested loop output (it resides outside of it), but what I don't get is why the file pointer is advanced to the next line upon calling the inner loop.

I have "2 inside" as part of the list (which is what I want), but I also would like to see "2 inside" be part of the inner loop output with its index next to it, but I can't figure out how to that. I even tried commenting out the lstItem.append(value) statement to see if it would keep the file pointer from advancing, but that just excludes that value from the list, which is not what I want.

Mike
  • 504
  • 7
  • 23

3 Answers3

1

The basic problem is that you're manipulating the file pointer in two places: each for loop. The phrase enumerate(f) iterates on the file descriptor f. You seem to think that this will apply to a buffered list of input already seen -- and this is not the case. The inner loop will continue through the file until it breaks out of that loop.

If you want only to iterate through what you've seen so far, then store the input lines in a list, and iterate on that list.

Does that get you moving?

Prune
  • 76,765
  • 14
  • 60
  • 81
0

The nested loop advances the pointer because you are iterating over file descriptor in the inner loop.

You should first read lines and then use your code using f.readlines(). You can then iterate over the lines in the nested loop.

Manthan Thakar
  • 209
  • 1
  • 9
0

I have "2 inside" as part of the list (which is what I want), but I also would like to see "2 inside" be part of the inner loop output with its index next to it

Simply print it out before entering the second loop:

    if "inside" in value:
        lstItem = []
        lstItem.append(value)
        print("inner loop (index:value): ", 0, value, end="")
        for i,value in enumerate(f, start=1):
            print("inner loop (index:value): ",i,value,end="")
            lstItem.append(value)
            if "outside" in value:
                break
        print(),print(lstItem),print()

So now there are two prints, the first with the index hardcoded as 0. Notice that the start=1 parameter is passed enumerate() so that it begins its count at 1.

Having two prints is a bit ugly. You can improve things a bit by printing after you have completed building lstItem:

    if "inside" in value:
        lstItem = []
        lstItem.append(value)
        for value in f:
            lstItem.append(value)
            if "outside" in value:
                break

        print(*('inner loop (index:value):  {} {}'.format(i, value)
                for i, value in enumerate(lstItem)), sep='')

        print(lstItem),print()

which produces this output:

outer loop (value):          1
outer loop (value):          2 inside
inner loop (index:value):  0 2 inside
inner loop (index:value):  1 3
inner loop (index:value):  2 4 outside

['2 inside\n', '3\n', '4 outside\n']

outer loop (value):          5
outer loop (value):          6
mhawke
  • 84,695
  • 9
  • 117
  • 138
  • Well, there was a bit more complex code wrapped around such that duplicates wouldn't be good, but I didn't want to overcomplicate the example. My goal was to figure out the file pointer issue, but it looks like the inner loop advances the file pointer, which seemed strange to me seeing as when you initially initialize a loop it doesn't advance the pointer beyond the first line. I also tried futzing with enumerate by changing the starting number, but still no luck. Like your example, I could use logic to print a better output, but it was more about what was happening with the loops. Thanks! – Mike May 03 '17 at 01:48
  • @Mike: As the quote from your question shows you did explicitly ask how to output that line in the inner loop. Anyway, as others have already answered, `enumerate()` will consume the data from the iterator (which is how the "file" object is being used). – mhawke May 03 '17 at 03:10