0

I have a problem in which I have a function which takes in an ID, and then checks for any invalid form of format within the ID.

The rules are:

1) ID must have a length of 5

2) The ID must start with a letter depending on the tribe name

3) The ID must end with a valid letter depending on average power

4) Contains three integers in between the two letters

ID Format: TNNNL In which: T - tribe name N - A digit L - A letter corresponding to the average power of an avatar

average power description

csv file:

name,tribe,id,Air,Water,Earth,Fire,Rule to test
Pema,Xero,X14C,24,54,34,43,Length of Avatar ID is not 5
Otaku,Taru,T111F,54,78,65,78,Invalid last letter
Aang,Nomad,NA21B,89,67,54,78,Invalid ID format
Zuko,Giant,A111C,48,54,98,75,Invalid first letter

My code:

import csv

def isValidAvatarIDFormat(ava_id):
    filePath = "data1.csv"
    with open(filePath) as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            tribe = row['tribe']
            air_power = row['Air']
            water_power = row['Water']
            earth_power = row['Earth']
            fire_power = row ['Fire']
            #check id length
            if(len(ava_id) != 5):
                return("Length of ID is not 5")
            #check first letter
            elif(ava_id[0] != tribe[0]):
                return("Invalid first letter")
            #check last letter
            elif(ava_id[4] != findAveragePower(air_power, water_power, earth_power, fire_power)):
                return("Invalid last letter")
            #check 3 digits in the middle
            elif bool(ava_id[1].isdigit() and ava_id[2].isdigit() and ava_id[3].isdigit()) == False:
                 return("Invalid ID format")

def findAveragePower(air_power, water_power, earth_power, fire_power):
        air_power = row['Air']
        water_power = row['Water']
        earth_power = row['Earth']
        fire_power = row ['Fire']
        average = int(int(air_power) + int(water_power) + int(earth_power) + int(fire_power)) / 4
        if(average >= 80):
            return "A"
        if(average >= 70 and average < 80):
            return "B"
        if(average >= 60 and average < 70):
            return "C"
        if(average >= 50 and average < 60):
            return "D"
        if(average >= 40 and average < 50):
            return "E"
        if(average <40):
            return "F"

#Main Program:
filePath = "data1.csv"
with open(filePath) as csvfile:
    reader = csv.DictReader(csvfile)
    print("{0:<5} | {1:^5} | {2:^5}".format("Avatar Name", "Avatar ID", "Comments"))
    for row in reader:
        string = isValidAvatarIDFormat(row['id'])
        print("{0:<11} | {1:<9} | {2:<15}".format(row['name'],row['id'], string))

Expected Output: I had expected the output to be the same as what was under the 'Rule to test' column in the CSV file. However the output was much more different than i expected.

Actual Output:

actual output

6
  • In how far are you dissatisfied with the output? Do you want just the "Comments" column? Do you want the same categories, e.g. Aang fails the invalid-id-format instead of invalid-first-letter? Do you want the same category texts, e.g. "Length of Avatar ID is not 5" instead of just "Length of ID is not 5"? Commented May 8, 2019 at 13:11
  • @MisterMiyagi I am not too concerned about the "comments" column, since I am returning the comments from my function. What I am concerned about is that the row['id'] values that are being passed into the function are giving the wrong invalid comments e.g. T111F should be Invalid last letter (due to avg. power > 39 (F)) and NB21B being an Invalid Format because the ID format should be in TNNNP Commented May 8, 2019 at 18:27
  • Please show an excerpt from your csv in plain text, not a screenshot from a viewer. Does it contain quotes or aligning whitespace perhaps? Does any correct ID successfully pass your validation? Commented May 9, 2019 at 4:21
  • @MisterMiyagi no whitespaces or quotes...All are meant to fail the validation and print out each individual error. But for now, only the first ID's invalid reason has been identified successfully Commented May 9, 2019 at 7:15
  • Let me rephrase that: Please be so kind and give people some sample data they can just copy/paste, instead of guessing and transcribing it from an Excel screenshot. Commented May 9, 2019 at 7:28

2 Answers 2

1

Every time you call isValidAvatarIDFormat, you start over to compare your id with the first row in your csv file.

Say, the second iteration in Main, where ID=T111F, when executing string = isValidAvatarIDFormat(row['id']), you start to compare the first letter of T111F with Xero, and that definitely gives you a false.

In order to make it work, I recommend to use the whole row (rather than only ID & reopen file) as the input of isValidAvatarIDFormat, for that's all the information you need.

def isValidAvatarIDFormat(row):
    ava_id = row['id']
    tribe = row['tribe']
    air_power = row['Air']
    water_power = row['Water']
    earth_power = row['Earth']
    fire_power = row ['Fire']
    #check id length
    if(len(ava_id) != 5):
        return("Length of ID is not 5")
    #check first letter
    elif(ava_id[0] != tribe[0]):
        return("Invalid first letter")
    #check last letter
    elif(ava_id[4] != findAveragePower(air_power, water_power, earth_power, fire_power)):
        return("Invalid last letter")
    #check 3 digits in the middle
    elif not bool(ava_id[1].isdigit() and ava_id[2].isdigit() and ava_id[3].isdigit()):
         return("Invalid ID format")

Update

If unable to change the input, here is another way like this:

# part of isValidAvatarIDFormat
for row in reader:
    if row['id'] != ava_id:
        continue
    else:
        all_your_other_operations
        break
Sign up to request clarification or add additional context in comments.

4 Comments

I understand what you mean, but the function needs to take in an id, not a row
1. plz provide more info on how result change/what error. 2. I just find out your findAveragePower dont work. you assign the variable again without using it, so the result becomes the 1st line of your csv again. After all it's no need to re-read your csv inside that func, you only have to calculate the average of your 4 inputs.
when I change it, the output shows "ID length is not 5" for all IDs in the CSV file.
cant figure out why, maybe you can try print the suspectious variables to find what's wrong. If all returns ID length not 5,probabaly means you made ava_id to be X14C
0

I removed:

tribe = row['tribe']

in isValidAvatarIDFormat() because I realized that every time I enter the function it calls the first tribe again, and therefore it would always return the output as an "invalid first letter". Since every value stored in 'tribe' would always be 'Xero' and it would always be compared to every ID in the file.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.