Nytro
Nytro

Reputation: 143

Add new line after finding last string in a region

I have this input test.txt file with the output interleaved as #Expected in it (after finding the last line containing 1 1 1 1 within a *Title region

and this code in Python 3.6

index = 0
insert = False
currentTitle = ""
testfile = open("test.txt","r")    
content = testfile.readlines()
finalContent = content
testfile.close()
# Should change the below line of code I guess to adapt
#titles = ["TitleX","TitleY","TitleZ"]   
 
for line in content:
    index = index + 1
    for title in titles:
        if line in title+"\n":    
            currentTitle = line
            print (line)
    if line == "1 1 1 1\n":
        insert = True
    if (insert == True) and (line != "1 1 1 1\n"):
        finalContent.insert(index-1, currentTitle[:6] + "2" + currentTitle[6:])
        insert = False
 
f = open("test.txt", "w")
finalContent = "".join(finalContent)
f.write(finalContent)
f.close()

Update:

Actual output with the answer provided

*Title Test
12125
124125
asdas 1 1 1 1 
rthtr 1 1 1 1 
asdasf 1 1 1 1 
asfasf 1 1 1 1 
blabla 1 1 1 1 
#Expected "*Title Test2" here <-- it didn't add it
124124124
*Title Dunno
12125
124125
12763125 1 1 1 1 
whatever 1 1 1 1
*Title Dunno2
#Expected "*Title Dunno2" here <-- This worked great
214142122

#and so on for thousands of them..

Also is there a way to overwrite this in the test.txt file?

Upvotes: 0

Views: 92

Answers (2)

tripleee
tripleee

Reputation: 189457

Because you are already reading the entire file into memory anyway, it's easy to scan through the lines twice; once to find the last transition out of a region after each title, and once to write the modified data back to the same filename, overwriting the previous contents.

I'm introducing a dictionary variable transitions where the keys are the indices of the lines which have a transition, and the value for each is the text to add at that point.

transitions = dict()
in_region = False
reg_end = -1
current_title = None

with open("test.txt","r") as testfile:
    content = testfile.readlines()

for idx, line in enumerate(content):
    if line.startswith('*Title '):
        # Commit last transition before this to dict, if any
        if current_title:
            transitions[reg_end] = current_title
        # add suffix for printing
        current_title = line.rstrip('\n') + '2\n'
    elif line.strip().endswith(' 1 1 1 1'):
        in_region = True
        # This will be overwritten while we remain in the region
        reg_end = idx
    elif in_region:
        in_region = False

 if current_title:
    transitions[reg_end] = current_title

with open("test.txt", "w") as output:
    for idx, line in enumerate(content):
        output.write(line)
        if idx in transitions:
            output.write(transitions[idx])

This kind of "remember the last time we saw something" loop is very common, but takes some time getting used to. Inside the loop, keep in mind that we are looping over all the lines, and remembering some things we saw during a previous iteration of this loop. (Forgetting the last thing you were supposed to remember when you are finally out of the loop is also a very common bug!)

The strip() before we look for 1 1 1 1 normalizes the input by removing any surrounding whitespace. You could do other kinds of normalizations, too; normalizing your data is another very common technique for simplifying your logic.

Demo: https://ideone.com/GzNUA5

Upvotes: 1

sushanth
sushanth

Reputation: 8302

try this, using itertools.zip_longest

from itertools import zip_longest

with open("test.txt","r") as f:
    content = f.readlines()

results, title = [], ""
for i, j in zip_longest(content, content[1:]):
    # extract title.
    if i.startswith("*"):
        title = i

    results.append(i)

    # compare value in i'th index with i+1'th (if mismatch add title)
    if "1 1 1 1" in i and "1 1 1 1" not in j:
        results.append(f'{title.strip()}2\n')

print("".join(results))

Upvotes: 1

Related Questions