Reset iteration index after using next() Python [duplicate] - python

This question already has answers here:
How can I iterate over overlapping (current, next) pairs of values from a list?
(12 answers)
Closed last month.
I am trying to edit a text file using fileinput.input(filename, inplace=1)
The text file has say 5 lines:
line 0
line 1
line 2
line 3
line 4
I wish to change data of line 1 based on info in line 2.
So I use a for loop
infile = fileinput.input(filename, inplace=1)
for line in infile:
if(line2Data):
#do something on line1
print line,
else:
line1=next(infile)
line2=next(infile)
#do something with line2
Now my problem is after the 1st iteration the line is set to line2 so in 2nd iteration the line is set to line3. I want line to be set to line1 in 2nd iteration. I have tried line = line but it doesn't work.
Can you please let me know how I am reset the iteration index on line which gets changed due to next
PS: This is a simple example of a huge file and function I am working on.

As far as I know (and that is not much) there is no way in resetting an iterator. This SO question is maybe useful. Since you say the file is huge, what I can think of is to process only part of the data. Following nosklos answer in this SO question, I would try something like this (but that is really just a first guess):
while True:
for line in open('really_big_file.dat')
process_data(line)
if some_condition==True:
break
Ok, your answer that you might want to start from the previous index is not captured with this attempt.

There is no way to reset the iterator, but there is nothing stopping your from doing some of your processing before you start your loop:
infile = fileinput.input("foo.txt")
first_lines = [next(infile) for x in range(3)]
first_lines[1] = first_lines[1].strip() + " this is line2 > " + first_lines[2]
print "\n".join(first_lines)
for line in infile:
print line
This uses next() to read the first 3 lines into a list. It then updates line1 based on line2 and prints all of them. It then continues to print the rest of the file using a normal loop.
For your sample, the output would be:
line 0
line 1 this is line2 > line 2
line 2
line 3
line 4
Note, if your are trying to modify the first lines of the file itself, rather than just display it, you would need to write the whole file to a new file. Writing to a file does not work like in a Word processor where all the lines move down when a line or character is added. It works as if you were in overwrite mode.

Related

Counting number of words and lines in a file in Python

How to write a function that reads a file and appends line number and the number of words in the line at the end of each line?
The expected output should be something like the following
Hello world, how are you? 1 5 # first line, 5 words
I am good. 2 3 #second line 3 words
Is it possible in python to have a def w() tha could open a file with a word count for every line and a line counter while still having the original text from the file?
Yes.
I'll give you a more concise answer than #ironkey however if you are new to python you might find theirs clearer.
with open('data.text', 'r') as f:
for line_cnt, line in enumerate(f, start=1):
word_cnt = len(line.split(" "))
print(line, f"| {line_cnt} | {word_cnt}")
Edit: Used enumerate as suggested to make it even shorter.

File operation starts again from first while looping through the file

I'm trying to find a certain word in a file and want to print the next line when a condition is met.
f = open('/path/to/file.txt','r')
lines = f.readlines()
for line in lines:
if 'P/E' in line:
n = lines.index(line) #get index of current line
print(lines[n+1]) #print the next line
a.close()
The string 'P/E' will be present 4 times in the file, each time in a different line.
When executed, the code prints the next line after the first 2 occurrences of 'P/E' normally. It then again goes back and prints the same first 2 occurrences again and exits. The loop is not proceeding after those first 2 occurrences; it kind of repeats the process and exits.
I checked the data file to see if my output is the actual result, but all next lines are different after 'P/E'.
How can I resolve this? Thanks.
list.index() with just one argument only finds the first occurrence. You'd have to give it a starting point to find elements past the previous index, list.index() takes a second argument that tells it where to start searching from.
However, you don't need to use lines.index(); that's very inefficient; it requires a full scan through the list, testing each line until a match is found.
Just use the enumerate() function to add indices as you loop:
for index, line in enumerate(lines):
if 'P/E' in line:
print(lines[index + 1])
Be careful, there is a chance index + 1 is not a valid index; if you find 'P/E' in the very last line of the lines list you'll get an IndexError. You may have to add a and index + 1 < len(lines) test.
Note that using file.readlines() reads all of the file into memory in one go. Try to avoid this; you could loop directly over the file, and remember the previous line instead:
with open('/path/to/file.txt','r') as f:
previous = ''
for line in f:
if 'P/E' in previous:
print(line) # print this line
previous = line # remember for the next iteration

Want to skip last and first 5 lines while reading file in python

If I want to see only data between line number 5 to what comes before last 5 rows in a file. While I was reading that particular file.
Code I have used as of now :
f = open("/home/auto/user/ip_file.txt")
lines = f.readlines()[5:] # this will start from line 5 but how to set end
for line in lines:
print("print line ", line )
Please suggest me I am newbie for python.
Any suggestions are most welcome too.
You could use a neat feature of slicing, you can count from the end with negative slice index, (see also this question):
lines = f.readlines()[5:-5]
just make sure there are more than 10 lines:
all_lines = f.readlines()
lines = [] if len(all_lines) <= 10 else all_lines[5:-5]
(this is called a ternary operator)

Re-ordering text file - Python

I must re-order an input file and then print the output to a new file.
This is the input file:
The first line never changes.
The second line was a bit much longer.
The third line was short.
The fourth line was nearly the longer line.
The fifth was tiny.
The sixth line is just one line more.
The seventh line was the last line of the original file.
This is what the output file should look like:
The first line never changes.
The seventh line was the last line of the original file.
The second line was a bit much longer.
The sixth line is just one line more.
The third line was short.
The fifth was tiny.
The fourth line was nearly the longer line.
I have code already that reverse the input file and prints it to the output file which looks like this
ifile_name = open(ifile_name, 'r')
lines = ifile_name.readlines()
ofile_name = open(ofile_name, "w")
lines[-1] = lines[-1].rstrip() + '\n'
for line in reversed(lines):
ofile_name.write(line)
ifile_name.close()
ofile_name.close()
Is there anyway I can get the desired format in the text file while keeping my reverse code?
Such as print the first line of the input file, then reverse and print that line, the print the second line of the input file, then reverse and print that line etc.
Sorry if this may seem unclear I am very new to Python and stack overflow.
Thanks in advance.
This is a much elegant solution I believe if you don't care about the list generated.
with open("ifile_name","r") as f:
init_list=f.read().strip().splitlines()
with open("result.txt","a") as f1:
while True:
try:
f1.write(init_list.pop(0)+"\n")
f1.write(init_list.pop()+"\n")
except IndexError:
break
ifile_name = "hello/input.txt"
ofile_name = "hello/output.txt"
ifile_name = open(ifile_name, 'r')
lines = ifile_name.readlines()
ofile_name = open(ofile_name, "w")
lines[-1] = lines[-1].rstrip() + '\n'
start = 0
end = len(lines) - 1
while start < end:
ofile_name.write(lines[start])
ofile_name.write(lines[end])
start += 1
end -= 1
if start == end:
ofile_name.write(lines[start])
ifile_name.close()
ofile_name.close()
use two pivots start and end to point which line to write to the file.
once start == end, write the middle line to the file

What qualifies collection of strings to become a line?

Following code is taking every character and running the loop as many times. But when I save the same line in a text file and perform same operation, the loop is only run once for 1 line. It is bit confusing. Possible reason I can think off is that first method is running the loop by considering "a" as a list. Kindly correct me if I am wrong. Also let me know how to create a line in code itself rather first saving it in a file and then using it.
>>> a="In this world\n"
>>> i=0
>>> for lines in a:
... i=i+1
... print i
...
1
2
3
4
5
6
7
8
9
10
11
12
13
You're trying to loop over a, which is a string. Regardless of how many newlines you have in a string, when you loop over it, you're going to go character by character.
If you want to loop through a bunch of lines, you have to use a list:
lines = ["this is line 1", "this is another line", "etc"]
for line in lines:
print line
If you have a string containing a bunch of newlines and want to convert it to a list of lines, use the split method:
text = "This is line 1\nThis is another line\netc"
lines = text.split("\n")
for line in lines:
print line
The reason why you go line by line when reading from a file is because the people who implemented Python decided that it would be more useful if iterating over a file yielded a collection of lines instead of a collection of characters.
However, a file and a string are different things, and you should not necessarily expect that they work in the same way.
Just change the name of the variable when looping on the line:
i = 0
worldLine ="In this world\n"
for character in worldLine:
i=i+1
print i
count = 0
readFile = open('myFile','r')
for line in readFile:
count += 1
now it should be clear what's going on.
Keeping meaningful names will save you a lot of debugging time.
Considering doing the following:
i = 0
worldLine =["In this world\n"]
for character in worldLine:
i=i+1
print i
if you want to loop on a list of lines consisting of worldLine only.

Categories