Reputation: 1
This is for an assignment which I've nearly finished. So the goal is to be able to search the list based on CID, which is the first value in each line of the txt file.
The text file contains the following records, and is tab delimited:
0001 001 -- -- 1234.00 -- -- 148.08 148.08 13.21 1395.29
0002 011 -- 100.00 12000.00 -- 5.00 1440.00 1445.00 414.15 13959.15
0003 111 100.00 1000.00 1000.00 8.00 50.00 120.00 178.00 17.70 2295.70
0004 110 1200.00 100.00 -- 96.00 5.00 -- 101.00 6.15 1407.15
0005 101 100.00 -- 1300.00 8.00 -- 156.00 164.00 15.60 1579.60
0006 100 1200.00 -- -- 96.00 -- -- 96.00 5.40 1301.40
0007 010 -- 1500.00 -- -- 75.00 -- 75.00 2.25 1577.25
0008 001 -- -- 1000.00 -- -- 120.00 120.00 9.00 1129.00
0009 111 1000.00 1000.00 1000.00 80.00 50.00 120.00 250.00 28.50 3278.50
0010 111 100.00 10000.00 1000.00 8.00 500.00 120.00 628.00 123.90 11851.90
Text file can be found here.
I'm new to Python, and haven't got my head around it yet. I need to be able to somehow dynamically fill in lines[0]
with other index positions. For example...'0002' is found in index [0], 0002 is found if I change to lines[1]
and so forth. I've tried various whiles, enumerating, list-comprehension, but most of that is beyond my understanding. Or maybe there's an easier way to display the line for a particular 'customer'?
with open('customer.txt', 'r') as file:
for line in file:
lines = file.read().split('\n')
search = input("Please enter a CID to search for: ")
if search in lines[0]:
print(search, "was found in the database.")
CID = lines[0]
print(CID)
else:
print(search, "does not exist in the database.")
Upvotes: 0
Views: 194
Reputation: 76695
Here's how I think you should solve this problem. Comments below the code.
_MAX_CID = 9999
while True:
search = input("Please enter a CID to search for: ")
try:
cid = int(search)
except ValueError:
print("Please enter a valid number")
continue
if not 0 <= cid <= _MAX_CID:
print("Please enter a number within the range 0..%d"% _MAX_CID)
continue
else:
# number is good
break
with open("customer.txt", "r") as f:
for line in f:
if not line.strip():
continue # completely blank line so skip it
fields = line.split()
try:
line_cid = int(fields[0])
except ValueError:
continue # invalid line so skip it
if cid == line_cid:
print("%d was found in the database." % cid)
print(line.strip())
break
else:
# NOTE! This "else" goes with the "for"! This case
# will be executed if the for loop runs to the end
# without breaking. We break when the CID matches
# so this code runs when CID never matched.
print("%d does not exist in the database." % cid)
Instead of searching for a text match, we are parsing the user's input as a number and searching for a numeric match. So, if the user enters 0, a text match would match every single line of your example file, but a numeric match won't match anything!
We take input, then convert it to an integer. Then we check it to see if it makes sense (isn't negative or too large). If it fails any test we keep looping, making the user re-enter. Once it's a valid number we break out of the loop and continue. (Your teacher may not like the way I use break
here. If it makes your teacher happier, add a variable called done
that is initially set to False
, and set it to True
when the input validates, and make the loop while not done:
).
You seem a bit confused about input. When you open a file, you get back an object that represents the opened file. You can do several things this object. One thing you can do is use method functions like .readlines()
or .read()
, but another thing you can do is just iterate it. To iterate it you just put it in a for
loop; when you do that, each loop iteration gets one line of input from the file. So my code sample sets the variable line
to a line from the file each time. If you use the .read()
method, you slurp in the entire file into memory, all at once, which isn't needed; and then your loop isn't looping over lines of the file. Usually you should use the for line in f:
sort of loop; sometimes you need to slurp the file with f.read()
; you never do both at the same time.
It's a small point, but file
is a built-in type in Python, and by assigning to that you are rebinding the name, and "shadowing" the built-in type. Why not simply use f
as I did in my program? Or, use something like in_file
. When I have both an input file and an output file at the same time I usually use in_file
and out_file
.
Once we have the line, we can split it into fields using the .split()
method function. Then the code forces the 0th field to an integer and checks for an exact match.
This code checks the input lines, and if they don't work, silently skips the line. Is that what you want? Maybe not! Maybe it would be better for the code to blow up if the database file is malformed. Then instead of using the continue
statement, maybe you would want to put in a raise
statement, and raise an exception. Maybe define your own MalformedDatabase
exception, which should be a subclass of ValueError
I think.
This code uses a pretty unique feature of Python, the else
statement on a for
loop. This is for code that is only executed when the loop runs all the way to the end, without an early exit. When the loop finds the customer ID, it exits early with a break
statement; when the customer ID is never found, the loop runs to the end and this code executes.
This code will actually work okay with Python 2.x, but the error checking isn't quite adequate. If you run it under Python 3.x it is pretty well-checked. I'm assuming you are using Python 3.x to run this. If you run this with Python 2.x, enter xxx
or crazy junk like 0zz
and you will get different exceptions than just the ValueError
being tested! (If you actually wanted to use this with Python 2.x, you should change input()
to raw_input()
, or catch more exceptions in the try
/except
.)
Upvotes: 1
Reputation: 174624
Another approach. Since the file is tab delimited, you can use the csv
module as well.
This approach, unlike @gnibbler's answer, will read the entire file and then search its contents (so it will load the file in memory).
import csv
with open('customer.txt') as file:
reader = csv.reader(file, delimiter='\t')
lines = list(reader)
search = input('Please enter the id: ')
result = [line for line in lines if search in line]
print '\t'.join(*result) if result else 'Not Found'
Upvotes: 0
Reputation: 304137
Not sure, are the lines supposed to be split into fields somehow?
search = input("Please enter a CID to search for: ")
with open('customer.txt', 'r') as file:
for line in file:
fields = line.split('\t')
if fields[0] == search:
print(search, "was found in the database.")
CID = fields[0]
print(line)
break
else:
print(search, "does not exist in the database.")
Upvotes: 2