I'm writing a code which reads some information from a file into a 2D array list. I then need to use a check_records function to validate each item on the list to make sure it meets certain requirements. i.e. each item contains an id, account etc. and those need to be a certain length and format. If the items don't meet these requirements they must be removed from the list. The number of valid and invalid items is then displayed on the screen.
However, my check_records function isn't working as intended. No matter what I do or change it refuses to validate more or less than 4 items from the list. It will invalidate any remaining items regardless of how many are in the list (from file). This happens seemingly at random, as the some items classed as valid are invalid and some classed as valid are actually invalid. It's not even validating the first 4 in the list, its just a random 4 from the list.
Looks like this on the screen:
**************************
UTOPIA BANK ATM LOG VIEWER
**************************
Enter the file name (include .txt extension): ATM_Log1.txt
--Log records loaded from (ATM_Log1.txt)--
Found (4) valid records. #Correct count (8 total items on list), incorrect items validated/invalidated
Found (4) invalid records.
#Items loaded into the list (printed just to show):
[['SYD127', '12823983', 'D', '20.00'], ['BHS115', '76530902', 'B', '0.50'], ['DUB796',
'50175864', 'W', '225.00'], ['PMQ426', '34957765', 'B', '5700.00']]
******************
MAIN MENU
******************
(1) Show all records
(2) Search by ATM ID
(3) Search by Account Number
(4) Search by Operation
(5) Exit
******************
Enter a choice:
Below is the section of code that I believe has the issue. While messing around will this part I have been able to get the program to accept all items as valid but not do what it's supposed to do. Changing other sections seems to have to effect on this particular issue.
overall_valid = None
for elem in log_records:
if not (id_valid == True and account_valid == True and operation_valid == True and
amount_valid == True):
overall_valid = False
for elem in log_records:
if overall_valid == False:
count = 1
log_records.remove(elem)
valid_records = len(log_records)
invalid_records = count
print(f"Found ({valid_records}) valid records.")
print(f"Found ({invalid_records}) invalid records.")
print(" ")
I have tried writing this multiple different ways and I posted previous question about another part of this code. Basically I'm at my limit of knowledge with this and I can't find a solution. Si I'm hoping that someone can give me some guidance on where I am going wrong. (I know my code isn't pretty and some stuff might be done in a weird way but I'm still learning).
The whole function for context if needed:
def check_records(log_records):
ID = [i[0] for i in log_records]
account = [i[1] for i in log_records]
operation = [i[2] for i in log_records]
amount = [i[3] for i in log_records]
count = 0
#-----------------------
#****Validate ATM ID****
letters = ID[0:2]
numbers = ID[3:]
id_valid = None
for elem in ID:
if len(elem) != 6:
valid = False
for elem in letters:
if len(letters) != 3:
valid = False
if not (elem.isalpha() for letters in ID for elem in letters):
valid = False
for elem in numbers:
if len(numbers) != 3:
valid = False
if not (elem.isalpha() for numbers in ID for elem in numbers):
valid = False
if valid != False:
valid = True
if valid == True:
id_valid = True
else:
id_valid = False
#-------------------------------
#****Validate Account Number****
account_valid = None
for elem in account:
if not elem.isdigit():
valid = False
#Account number must be 8 digits long.
if len(str(account)) != 8:
valid = False
#If the account number meets all requirments then it is valid.
if valid != False:
valid = True
#Account number will be returned as either true or false.
if valid == True:
account_valid = True
else:
account_valid = False
#-------------------------------
#****Validate Operation****
operation_valid = None
for elem in operation:
#Operation must be B, D or W.
if operation != 'B' or 'D' or 'W':
valid = False
if valid != False:
valid = True
#If the operation meets all requirments then it is valid.
if valid == True:
operation_valid = True
else:
operation_valid = False
#-------------------------------
#****Validate Amount****
amount_valid = None
for elem in amount:
#Amount must be a float number
if amount != float:
valid = False
if amount == float:
valid = True
#If the amount meets all requirments then it is valid.
if valid == True:
amount_valid = True
else:
amount_valid = False
REST CONTINUES AS SHOWN EARLIER (PROBLEM CODE)
CodePudding user response:
Issues with posted code
- The first obvious issue with function check_records:
- variable valid is not assigned before the for loop (i.e. should be True),
- letters are defined as the first two IDs (i.e.
letters = ID[0:2]
) and numbers to the remaining. Are you trying to check if the first 3 characters of each ID are numeric and the last 3 characters are letters?
- Assigning letters to ID[0:2] is incorrect since this is just the first two IDs rather than the letters of each ID
if operation != 'B' or 'D' or 'W':
is the incorrect multiple condition if statement for your purpose (i.e. this conditional is always True). Search stackoverflow python for multiple condition if statement- An option is to have Boolean lists for id_valid, amount_valid, operation_valid, amount_valid that will contain the validity of each log_record. The value will be set based on whether the corresponding log_record is valid or not
Corrections
def check_records(log_records):
ID = [i[0] for i in log_records] # ID is first field
account = [i[1] for i in log_records] # account second field
operation = [i[2] for i in log_records] # operation third field
amount = [i[3] for i in log_records] # amount 4th field
# Boolean for validity of each field in record (initialize all to True)
id_valid = [True for _ in range(len(log_records))]
account_valid = [True for _ in range(len(log_records))]
operation_valid = [True for _ in range(len(log_records))]
amount_valid = [True for _ in range(len(log_records))]
#-----------------------
#****Validate ATM ID****
for index, elem in enumerate(ID):
if len(elem) != 6:
id_valid[index] = False
else:
letters = elem[0:3] # first 3 characters of current ID
numbers = elem[3:] # characters in ID after first 3
if len(letters) != 3 or not letters.isalpha():
id_valid[index] = False
elif len(numbers) != 3 or not numbers.isnumeric():
id_valid[index] = False
#-------------------------------
#****Validate Account Number****
for index, elem in enumerate(account):
account_valid[index] = len(elem) == 8 and elem.isnumeric()
#-------------------------------
#****Validate Operation****
for index, elem in enumerate(operation):
operation_valid[index] = elem in ["B", "D", "W"]
#-------------------------------
#****Validate Amount****
def isfloat(num):
' Checks if string is float'
try:
float(num)
return True
except ValueError:
return False
for index, elem in enumerate(amount):
amount_valid[index] = isfloat(elem)
overall_valid = [(id_valid[index] and
account_valid[index] and
operation_valid[index] and
amount_valid[index]) for index in range(len(log_records))]
# Keep only valid records
log_records = [rec for index, rec in enumerate(log_records) if overall_valid[index]]
valid_records = len(log_records)
invalid_records = len(overall_valid) - sum(overall_records)
print(f"Found ({valid_records}) valid records.")
print(f"Found ({invalid_records}) invalid records.")
print(" ")