简体   繁体   中英

How to read a specific line which is above the current line from a file using python

I have a file, after reading a line from the file I have named it current_line , I want to fetch the 4th line above the current_line. How can this be done using python?

line 1
line 2
line 3
line 4
line 5
line 6

Now say I have fetched line 6 and I have made

current_line = line 6

Now i want 4 the line from above (ie) N now want line 2

output_line = line 2

PS: I dont want to read the file from bottom.

You can keep a list of the last 4 lines while iterating over the lines of your file. A good way to do it is to use a deque with a maximum length of 4:

from collections import deque

last_lines = deque(maxlen=4)

with open('test.txt') as f:
    for line in f:
        if line.endswith('6\n'): # Your real condition here
            print(last_lines[0])  
        last_lines.append(line)

#  Output:
# line 2

Once a bounded length deque is full, when new items are added, a corresponding number of items are discarded from the opposite end.

We read the file line by line and only keep the needed lines in memory.

Imagine we have just read line 10. We have lines 6 to 9 in the queue.

If the condition is met, we retrieve line 6 at the start of the queue and use it.

We append line 10 to the deque, the first item (line 6) gets pushed out, as we are sure that we won't need it anymore, we now have lines 7 to 10 in the queue.

My approach would be converting the contents to a list splitting on \\n and retrieving required line by index.

lines = '''line 1
line 2
line 3
line 4
line 5
line 6'''

s = lines.split('\n')
current_line = 'line 6'

output_line = s[s.index(current_line) - 4]
# line 2

Since you are reading from file, you don't need to explicitly split on \\n . You could read from file as list of lines using readlines :

with open('path/to/your_file') as f:
    lines = f.readlines()
    current_line = 'line 6'
    output_line = lines[lines.index(current_line) - 4]
    # line 2

You can use enumerate for your open() . For example:

with open('path/to/your.file') as f:
    for i, line in enumerate(f):
        # Do something with line
        # And you have the i as index.

To go back to the i-4 line, you may think about using while .

But why do you need to go back?

you can do:

with open("file.txt") as f:
    lines = f.readlines()

for nbr_line, line in enumerate(lines):
    if line == ...:
        output_line = lines[nbr_line - 4] # !!! nbr_line - 4 may be < 0

As I can see you are reading the file line by line. I suggest you to read whole file into the list as below example.

with open("filename.txt","r") as fd: lines=fd.readlines() # this will read each line and append it to lines list

lines[line_number] will give you the respected line.

f.readLines not effective solution. If you work on huge file why do you want to read all file into memory?

def getNthLine(i):
    if i<1:
        return 'NaN';
    else:
        with open('temp.text', 'r') as f:
            for index, line in enumerate(f):
                if index == i:
                    line = line.strip()
                    return line

f = open('temp.text','r');

for i,line in enumerate(f):
    print(line.strip());
    print(getNthLine(i-1));

There is no much more options to solve that kind of a problem. you could also use tell and seek methods to play around but generally no need for ninja :).

If you using on huge file just do not forget to use enumerate

This is how you could do it with a generator, avoids reading the whole file into memory.

Update : used collections.deque (deque stands for "double ended queue") as recommended by Thierry Lathuille.

import collections

def file_generator(filepath):
    with open(filepath) as file:
        for l in file:
            yield l.rstrip()

def get_n_lines_previous(filepath, n, match):
    file_gen = file_generator(filepath)
    stored_lines = collections.deque('',n)

    for line in file_gen:
        if line == match:
            return stored_lines[0]        
        stored_lines.append(line)

if __name__ == "__main__":
    print(get_n_lines_previous("lines.txt", 4, "line 6"))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM