I am trying to create a 'check records' function which accepts a 2D list (ID
, account
, operation
, amount
) and returns the number of valid or invalid items on the list. Which is based on set criteria. Each of the criteria also has its own function i.e. validate account number is a function which validates a list of account numbers.
The check records function then will look at the results of all the validate functions and remove any items from the full 2D list which has any part as invalid (returning false).
The full list looks something like this (For context):
[['SYD123', '12823983', 'B', '150.00'], ['SYD127', '12823983', 'D', '20.00'], ['BHS115', '85849276', 'B', '1000.85'], ['BHS115', '76530902', 'B', '0.50'], ['BMT251', '49468141', 'W', '500.00'], ['DUB796', '50175864', 'W', '225.00'], ['WGA584', '34957765', 'D', '2500.00'], ['PMQ426', '34957765', 'B', '5700.00']]
and prints like this:
[List table format][1]
The issue I'm having is that I'm always getting 4
valid and 0
invalid being returned. No matter how many there actually is. I believe the issue is because the variables below are only pointing to one element of the original list above. I need them to be the entire column with the relevant variable? If this is wrong please point me in the right direction.
What I'm getting:
Found (4) valid records.
Found (0) invalid records.
Items it thinks are valid (all should be valid):
[['SYD127', '12823983', 'D', '20.00'], ['BHS115', '76530902', 'B', '0.50'], ['DUB796', '50175864', 'W', '225.00'], ['PMQ426', '34957765', 'B', '5700.00']]
The problem code looks like this:
def check_records(log_records):
#THESE VARIABLES!!!!!
ID = log_records [0]
account = log_records [1]
operation = log_records [2]
amount = log_records [3]
#HERE!!!!!!
overall_valid = False
count = 0
#Use validate functions to get a valid or invalid record.
validate_atm_id(ID)
validate_account(account)
validate_operation(operation)
validate_amount(amount)
if validate_atm_id == True and validate_account == True and validate_operation == True and
validate_amount == True:
overall_valid = True
else:
overall_valid = False
for elem in log_records:
if overall_valid == False:
count 1
log_records.remove(elem)
total_records = len(log_records)
invalid_records = count
valid_records = total_records - invalid_records
print(f"Found ({valid_records}) valid records.")
print(f"Found ({invalid_records}) invalid records.")
print(" ")
One of the validate functions (for extra context):
def validate_account(account):
valid = False
#Account number must be 8 digits long.
if len(account) != 8:
valid = False
#Account number must only contain numbers.
elif not account.isdigit():
valid = False
#If the account number meets all requirments then it is valid.
else:
valid = True
if valid == True:
return True
elif valid == False:
return False
CodePudding user response:
Im going to leave some parts as an excersize to the reader
first understand how indexing works
a = [11,12,13]
a[0] # gets the first element (11)
next understand what you are indexing into
organized_by_rows = [
["r1c1","r1c2","r1c3","r1c4"],
["r2c1","r2c2","r2c3","r2c4"]
]
organized_by_rows[0] # gets first element (["r1c1","r1c2","r1c3","r1c4"])
now what you need to do is basically turn your rows on their side into columns, this is known as transposing
organized_by_cols = [
["r1c1","r2c1"],
["r1c2","r2c2"],
["r1c3","r2c3"],
["r1c4","r2c4"],
]
organized_by_cols[0] # gets first element (["r1c1","r2c1"])
# ie gets the first column
there are many ways to do this, but python provides a pretty simple builtin way
organized_by_cols = zip(*organized_by_rows)
using this info I am confident you can find your solution
CodePudding user response:
You can create column-like structures with list comprehensions:
ids = [i[0] for i in log_records] # assumming log_records is your full list
accounts = [i[1] for i in log_records]
operations = [i[2] for i in log_records]
amounts = [i[3] for i in log_records]
Although I'd not recommend doing it because what you want to check are individual records and if you create column-like variables you'll have to deal with a lot of indexing and it's a bit painful.
Also this is unnecessarily long:
if validate_atm_id == True and validate_account == True and validate_operation == True and
validate_amount == True:
overall_valid = True
I'd rewrite it as:
overall_valid = True
if not any((validate_atm_id, validate_account, validate_operation, validate_amount )):
overall_valid = False
This looks like a typo:
for elem in log_records:
if overall_valid == False:
count 1 # this line shouldn't work and should be "count = 1"
log_records.remove(elem)