Home > Software design >  Using enumerate function to iterate over a file
Using enumerate function to iterate over a file

Time:04-26

I have a file with about 50 blocks of 14 lines, with each block starting with certain string that I can search for. Since the file is otherwise fairly large, I am using the enumerate function as:

def search_and_return_a_block(l_no,file_path, string):
    with open(file_path, 'r') as file:
        for l_no, line in enumerate(file):
                if string in line:
                     #append lines into a list of 14 lines
                     break
        return list,l_no

Now, I want only the top 2 blocks out of the 50, so when I call this function, I wish to start searching from the bottom of the 1st block and not from the beginning of the file. The function does return correct line number the first time.

However, the above for loop always start from 0 and ignores the value of its first argument (l_no) I call it with. This causes it to print only the first block 2 times and not move onto the next block.

I also tried to use the optional argument of the enumerate function with no success. Is there an elegant way to do this?

CodePudding user response:

I'm not comletely sure about what you want to achieve, and I'm no Python 2 expert (anymore), so this might not be what you are looking for:

from itertools import islice

def search_and_return_a_block(start, file_path, string):
    block = []
    no = start
    with open(file_path, 'r') as file:
        for no, line in enumerate(islice(file, start, None), start=start   1):
            block.append(line.rstrip()) 
            if string in line:
                 break
    return block, no

If you run

start = 0
for _ in range(10):
    block, start = search_and_return_a_block(start, 'file.txt', 'a')
    print(block, start)

for file.txt like

a
b
c
a
b
c
d
a
b
c
d
e
a
b
a
a
a
b
c
d

you'll get the following output:

['a'] 1
['b', 'c', 'a'] 4
['b', 'c', 'd', 'a'] 8
['b', 'c', 'd', 'e', 'a'] 13
['b', 'a'] 15
['a'] 16
['a'] 17
['b', 'c', 'd'] 20
[] 20
[] 20

But maybe a generator function would be a better fit to your needs? You could do something like:

def search_and_return_a_block(start_block, file_path, string):
    with open(file_path, 'r') as file:
        blocks = 1
        out = True if start_block == 1 else False
        block = []
        for line in file:
            if out:
                block.append(line.rstrip()) 
                if string in line:
                    yield block
                    block = []
            elif string in line:
                blocks  = 1
                if blocks == start_block:
                    out = True

When you do the following with the same file

blocks = search_and_return_a_block(2, 'file.txt', 'a')
block_2 = next(blocks)
print(block_2)
block_3 = next(blocks)
print(block_3)

the result would look like

['b', 'c', 'a']
['b', 'c', 'd', 'a']
  • Related