Home > Blockchain >  Python - How to set a variable to a specific column in a 2D list? Is it possible?
Python - How to set a variable to a specific column in a 2D list? Is it possible?

Time:10-01

I'm having some issues with my code and this is going to be kind long so please bare with me.

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

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

I have been working on this for a while and this is the last thing I need to figure out for this code (it is much bigger than just this part and does other things as well). I'm still pretty new to this so I'm sorry if anything is too confusing. Any help would be really amazing.

!!!!!UPDATE!!!!!! my code is now correctly count the number of valid and invalid items in the list. However, no matter what I do it refuses to count more or less then 4 as valid. Even if I force my functions to return a false value which should make all of the items in the list invalid. my code is now:

for elem in log_records:
    if (validate_atm_id(ID) == True and validate_account(account) == True and 
    validate_operation(operation) == True and validate_amount(amount) == True):
        overall_valid = True

for elem in log_records:
    if not (validate_atm_id(ID) == True and validate_account(account) == True and 
    validate_operation(operation) == True and validate_amount(amount) == True):
        overall_valid = False
        if overall_valid == False:
            count  = 1
            log_records.remove(elem)    

#The number of valid and invalid records is calculated and printed to the screen.
valid_records = len(log_records)
invalid_records = count
print(f"Found ({valid_records}) valid records.")
print(f"Found ({invalid_records}) invalid records.")
print(" ")

Changing this section is the only thing that has any impact on what is being classes as valid or invalid which makes me think the issue MUST be here somewhere. Even messing with the functions I'm using to validate doesn't change the results. It doesn't even appear to be using them, or else they are all returning true no matter what.

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)

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

  • Related