blazePascal
blazePascal

Reputation: 35

Deleting a line in file containing exact string (Python)

import re
print "List of names:"
f=open('names.txt','r')  #look below
lines = f.readlines()
for line in lines:
    info = line.split('|')
    names = info[0]
    print names
name = raw_input("Enter the name of the person you want to delete: ")
f.close()

f = open('names.txt','w')
for line in lines:
    if not re.match(name,line):
        f.write(line)
        break

print "That person doesn't exist!"

names.txt :

John|22|Nice
Johnny|55|Better than John
Peter|25|The worst

So, when you run the program, list of names is printed and then you have to enter the name of the person whose line you want to delete.

The problem is, if I enter John, it deletes the first and the second line, but I want only the first line to be deleted. My guess is that I'm not doing re.match() right. I tried re.match(name,names) but that doesn't work either.

So, the string you enter into name should be compared to the strings in names , and if there's an exact match, it should delete the line that has name as the first element.

I found a lot of similar problems but my function contains everything combined and I can't figure it out.

Upvotes: 0

Views: 1158

Answers (2)

Padraic Cunningham
Padraic Cunningham

Reputation: 180441

  with open("in.txt") as f:
    lines = f.readlines()
    name = raw_input("Enter the name of the person you want to delete: ").lower() + "|"
    ln = len(name)
    for ind, line in enumerate(lines):
        if name == line[:ln].lower():
            lines[ind:ind+1] = []
            break
    with open("in.txt","w") as out:
        out.writelines(lines)

If you want to remove all John's etc.. don't break just keep looping and writing, as it stands we erase the first "John" we find. The fastest way is to just index.

Upvotes: 0

volcano
volcano

Reputation: 3582

re.match matches the string at the beginning of the string. You may add word delimeter to your expression

name + r'\b'

but in your case, re is an overkill, simple comparison will do

name == line.partition('|')[0]

BTW, if you need to split only once at the beginning - or end - partition and rpartition functions are better options

EDIT

Timing:

    >>> timeit('line.startswith(name+"|")', 'line="John|22|Nice";name="John"')
    0.33100164101452345

    >>> timeit('line.partition("|")[0] == name', 'line="John|22|Nice";name="John"')
    0.2520693876228961

    >>> timeit('re.match(name+r"\b", line)', 'import re; line="John|22|Nice";name="John"')
1.8754496594662555

    >>> timeit('line.split("|")[0] == name', 'line="John|22|Nice";name="Jonny"') 
    0.511219799415926

Especially for Padraick

>>> timeit('line.partition("|")[0] == name', 'line="John|22|Nice";name="John"')
0.27333073995099083
>>> timeit('line.split("|", 1)[0] == name', 'line="John|22|Nice";name="John"')
    0.5120651608158937

Frankly - I am surprised myself

Upvotes: 1

Related Questions