Reputation: 23
I am working on an assignment for school and have hit a wall.
The challenge is:
You will be passed the filename P, firstname F, lastname L, and a new birthday B.
Load the fixed length record file in P, search for F,L in the first and change birthday to B.
Then save the file.
I have managed to read from the file and split the data into the desired entries in a list.
However, my issue arises when I am searching for the first and last name in the list.
The first and last name being passed is Adam Smith, but there is also an Adam Smithers in the list who is found by my code as well.
When I attempt to replace the desired element of the list, it is replacing it for both Smith and Smithers.
We cannot use regular expressions for the assignment, so I am at a bit of a loss for how to approach this and find an exact match for the last name while ignoring the other last name that contains Smith without using regex.
Here's my code:
import sys
P= sys.argv[1]
F= sys.argv[2]
L= sys.argv[3]
B= sys.argv[4]
filePath = P
firstName = F
lastName = L
newBirthday = B
records = []
file1 = open(filePath, 'r')
fileContent = file1.read()
while len(fileContent) > 0:
record = []
fname = fileContent[0:16]
lname = fileContent[16:32]
bday = fileContent[32:40]
record = [fname,lname,bday]
records.append(record)
fileContent = fileContent[40:]
for record in records:
if firstName in record[0] and lastName in record[1]:
record[2] = newBirthday
file1.close()
file2 = open(filePath, 'w')
for record in records:
file2.write(record[0])
file2.write(record[1])
file2.write(record[2])
file2.close()
Any ideas or hints that someone would be able to provide will be most appreciated.
Thanks!
Edit:
Icewine was kind enough to suggest using the below instead:
if firstName == record[0] and lastName == record[1]:
However, when I try that, it does not find any matching records.
I believe this is because there as blank spaces after each name to make up 16 characters in each name, giving a fixed length for the name. So when I'm using the == operator, it's not finding an exact match because there are also blank spaces in the name, so it's not an exact match.
Upvotes: 2
Views: 327
Reputation: 16495
Here are a few improvements I could suggest to your code:
if __name__ == '__main__':
. You can google why.with open(file_path, 'r') as f:
to read and write files; it looks cleaner and you won't forget to close the file.line[:16].strip()
.you read in specified widths, so don't forget to write back into the file with those same widths. This code ensures that each part of the record has the specified width:
f.write('{:16s}{:16s}{:8s}'.format(*record))
Here is my version of the code:
import sys
if __name__ == '__main__':
file_path = sys.argv[1]
first_name = sys.argv[2]
last_name = sys.argv[3]
new_birth_date = sys.argv[4]
record_list = []
with open(file_path, 'r') as f:
while True:
line = f.read(40) # read 40 chars at the time
if len(line) == 0:
# the end of the file was reached
break
record = [
line[:16].strip(),
line[16:32].strip(),
line[32:].strip(),
]
if first_name == record[0] and last_name == record[1]:
record[2] = new_birth_date
record_list.append(record)
with open(file_path, 'w') as f:
for record in record_list:
f.write('{:16s}{:16s}{:8s}'.format(*record))
Does this work for you?
Note: this code does not split lines by newlines, but it reads 40 chars at the time, so you could end up with a newline char inside those 40 chars.
I did it this way because the code in the question seems to do something similar.
Upvotes: 0
Reputation: 389
An easy solution to this would be to sort the list of names and values (in this case, birthdays (I suggest you use a dictionary for this purpose) and then perform a search operation that finds only the first occurrence of an element. That way only Adam Smith
is selected.
You can then further deal with duplicates by checking if the next element is the same as the one you found.
i.e. if the first occurrence is i
, check if i+1 == i
, and update all of the duplicates. (this may be what you need to do for your exercise, though it doesn't make sense to update other people's birthdays like this.)
Hopefully this helps :)
Upvotes: 0
Reputation: 49320
Either pad spaces onto the passed data to match what's in the file:
firstName = f'{F:<16}'
or strip the extra spaces from the file contents to match the passed data:
fname = fileContent[0:16].strip()
then you can simply compare the names, either keeping the in
operator or using ==
.
Upvotes: 1
Reputation: 105
Trim the whitespaces in the string and then use ==
for matching. This will give the expected output. Sample code
for record in records:
if firstName == record[0].strip() and lastName == record[1].strip():
record[2] = newBirthday
Upvotes: 1
Reputation: 1851
Use == instead of in
if firstName == record[0] and lastName == record[1]:
EDIT: try this
Removes whitespace from end of string
if firstName.rstrip() == record[0].rstrip() and lastName.rstrip() == record[1].rstrip()
or
Removes whitespace from start and end of string
if firstName.strip() == record[0].strip() and lastName.strip() == record[1].strip()
Upvotes: 1