1

I have an input file.txt like this:

3
2
A
4
7
B
1
9
5
2
0       

I'm trying to read the file and

  • when A is found, print the line that is 2 lines below
  • when B is found, print the line that is 4 lines below

My current code and current output are like below:

with open('file.txt') as f:
    for line in f:
        if 'A' in line: ### Skip 2 lines!
            f.readline()        ### Skipping one line
            line = f.readline() ### Locate on the line I want
            print(line) 
        if 'B' in line: ## Skip 4 lines
            f.readline()        ### Skipping one line
            f.readline()        ### Skipping two lines
            f.readline()        ### Skipping three lines
            line = f.readline() ### Locate on the line I want
            print(line)             
        
'4\n'
7

'1\n'
'9\n'
'5\n'
2       
>>>

Is printing the values I want, but is printing also 4\n,1\n... and besides that, I need to write several f.realines()which is not practical.

Is there a better way to do this?

My expected output is like this:

7
2
vvvvv
  • 25,404
  • 19
  • 49
  • 81
Ger Cas
  • 2,188
  • 2
  • 18
  • 45
  • how are you running the code? If you are using IPython or Jupyter notebook that might be why you are getting extra outputs because I don't see any reason `'1\n'` would show up like that in the output based on the code you have. – Tadhg McDonald-Jensen Jul 15 '20 at 21:14
  • I cannot reproduce what you are describing. The only thing is that it prints the lines (7 and 2) including a newline. You can strip the resulting line with `line.strip()` – Ronald Jul 15 '20 at 21:14
  • Based no the first comment: try 'consuming' the `f.readline()` with a dummy variable: `_ = f.readline()` – Ronald Jul 15 '20 at 21:15
  • I'm run it on Ubuntu shell in test mode. – Ger Cas Jul 15 '20 at 21:21

2 Answers2

2

Here is a much simpler code for you:

lines=open("file.txt","r").read().splitlines()
#print(str(lines))
for i in range(len(lines)):
    if 'A' in lines[i]:
        print(lines[I+2]) # show 2 lines down
    elif 'B' in lines[i]:
        print(lines[I+4]) # show 4 lines down

This reads the entire file as an array in which each element is one line of the file. Then it just goes through the array and directly changes the index by 2 (for A) and 4 (for B) whenever it finds the line it is looking for.

Tadhg McDonald-Jensen
  • 20,699
  • 5
  • 35
  • 59
vc2310
  • 131
  • 1
  • 1
  • 7
  • note that this doesn't actually skip those lines in the iteration, after changing `i` within an. iteration the for loop will walk it back and go over each line that was skipped unlike the original code which iterates over the file. Not necessarily a bad thing in this simple case but assuming there is more complicated things happening in the code this can lead to very subtle differences. – Tadhg McDonald-Jensen Jul 15 '20 at 22:13
  • Thanks so much for your solution. It could work in some cases. Regards – Ger Cas Jul 15 '20 at 23:17
1

if you don't like repeated readline then wrap it in a function so the rest of the code is very clean:

def skip_ahead(it, elems):
    assert elems >= 1, "can only skip positive integer number of elements"
    for i in range(elems):
        value = next(it)
    return value

with open('file.txt') as f:
    for line in f:
        if 'A' in line:
            line = skip_ahead(f, 2)
            print(line) 
        if 'B' in line:
            line = skip_ahead(f, 4)
            print(line)             
    

As for the extra output, when the code you have provided is run in a standard python interpreter only the print statements cause output, so there is no extra lines like '1\n', this is a feature of some contexts like the IPython shell when an expression is found in a statement context, in this case f.readline() is alone on it's own line so it is detected as possibly having a value that might be interesting. to suppress this you can frequently just do _ = <expr> to suppress output.

Tadhg McDonald-Jensen
  • 20,699
  • 5
  • 35
  • 59