Savina Dimitrova
Savina Dimitrova

Reputation: 155

Error with .readlines()[n]

I'm a beginner with Python. I tried to solve the problem: "If we have a file containing <1000 lines, how to print only the odd-numbered lines? ". That's my code:

with open(r'C:\Users\Savina\Desktop\rosalind_ini5.txt')as f:
   n=1
   num_lines=sum(1 for line in f)
   while n<num_lines:
         if n/2!=0:
                 a=f.readlines()[n]
                 print(a)
         break
    n=n+2

where n is a counter and num_lines calculates how many lines the file contains. But when I try to execute the code, it says:

"a=f.readlines()[n]
 IndexError: list index out of range"

Why it doesn't recognize n as a counter?

Upvotes: 2

Views: 1499

Answers (4)

Andy
Andy

Reputation: 263

As a fix, you need to type

f.close()
f = open(r'C:\Users\Savina\Desktop\rosalind_ini5.txt')

everytime after you read through the file, in order to get back to the start.

As a side note, you should look up modolus % for finding odd numbers.

Upvotes: 0

gboffi
gboffi

Reputation: 25093

You have the call to readlines into a loop, but this is not its intended use, because readlines ingests the whole of the file at once, returning you a LIST of newline terminated strings.

You may want to save such a list and operate on it

list_of_lines = open(filename).readlines() # no need for closing, python will do it for you
odd = 1
for line in list_of_lines:
    if odd : print(line, end='')
    odd = 1-odd

Two remarks:

  1. odd is alternating between 1 (hence true when argument of an if) or 0 (hence false when argument of an if),
  2. the optional argument end='' to the print function is required because each line in list_of_lines is terminated by a new line character, if you omit the optional argument the print function will output a SECOND new line character at the end of each line.

Coming back to your code, you can fix its behavior using a

f.seek(0)

before the loop to rewind the file to its beginning position and using the f.readline() (look, it's NOT readline**S**) method inside the loop, but rest assured that proceding like this is. let's say, a bit unconventional...

Eventually, it is possible to do everything you want with a one-liner

print(''.join(open(filename).readlines()[::2]))

that uses the slice notation for lists and the string method .join()

Upvotes: 2

Michel Touw
Michel Touw

Reputation: 626

This code will do exactly as you asked:

with open(r'C:\Users\Savina\Desktop\rosalind_ini5.txt')as f:
    for i, line in enumerate(f.readlines()):   # Iterate over each line and add an index (i) to it.
        if i % 2 == 0:       # i starts at 0 in python, so if i is even, the line is odd
            print(line)

To explain what happens in your code:

A file can only be read through once. After that is has to be closed and reopened again.

You first iterate over the entire file in num_lines=sum(1 for line in f). Now the object f is empty.

If n is odd however, you call f.readlines(). This will go through all the lines again, but none are left in f. So every time n is odd, you go through the entire file. It is faster to go through it once (as in the solutions offered to your question).

Upvotes: 0

Cajuu&#39;
Cajuu&#39;

Reputation: 1166

Well, I'd personally do it like this:

def print_odd_lines(some_file):
    with open(some_file) as my_file:
        for index, each_line in enumerate(my_file):  # keep track of the index of each line
            if index % 2 == 1:  # check if index is odd
                print(each_line)  # if it does, print it

if __name__ == '__main__':
    print_odd_lines('C:\Users\Savina\Desktop\rosalind_ini5.txt')

Be aware that this will leave a blank line instead of the even number. I'm sure you figure how to get rid of it.

Upvotes: 0

Related Questions