2

I'm trying to make a script that will ask for 5 score input from the user. Each score corresponds to a specific dilution. The input are strings and only six "characters" are allowed to be entered and q to quit the script and show each dilution with their score that have been entered. The problem is that when a invalid "character" is used it skips the dilution completely and does not add it to the dictionary and what I want is to retry the input for the specific dilution.

dil = ["1:16", "1:32", "1:64", "1:128", "1:256"]
corr_input = ["+", "++-", "-", "+-", "-a", "A"]
scores = {}

for dil in dil:
    testscore = input("Enter score: ")
    try:
        if testscore in corr_input:
            scores[dil] = testscore
        elif testscore == "q":
            print("Done!")
            break
        else:
            print("Not a valid score!")
    except TypeError:
        print("Invalid input! Try again")
        break
print(scores)

What I get!

######### 
Enter score: +
Enter score: +
Enter score: v
Not a valid score!
Enter score: +
Enter score: +
{'1:16': '+', '1:32': '+', '1:128': '+', '1:256': '+'}`
1
  • This question is similar to: repeat an iteration of for loop. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Jun 26 at 21:03

2 Answers 2

2

The typical way of accomplishing this is with a nested loop. For every dilution, you want a sub-loop that runs until a valid score (or q) is entered.

dil = ["1:16", "1:32", "1:64", "1:128", "1:256"]
corr_input = ["+", "++-", "-", "+-", "-a", "A"]
scores = {}

for dil in dil:
    while dil not in scores:  # This loop will run until the dilution has a score
        testscore = input("Enter score: ")
        try:
            if testscore in corr_input:
                scores[dil] = testscore
            elif testscore == "q":
                print("Done!")
                exit()  # Use exit() to exit the program with 'q'
            else:
                print("Not a valid score! Try again")
        except TypeError:
            print("Invalid input! Try again")

print(scores)

Note that the above example uses exit() to break out of both loops at once, instantly ending the program. Alternatively, you will need to use a variable like to_exit to break out of the outer for loop, like so:

dil = ["1:16", "1:32", "1:64", "1:128", "1:256"]
corr_input = ["+", "++-", "-", "+-", "-a", "A"]
scores = {}

to_exit = False

for dil in dil:
    while dil not in scores:  # This loop will run until the dilution has a score
        testscore = input("Enter score: ")
        try:
            if testscore in corr_input:
                scores[dil] = testscore
            elif testscore == "q":
                print("Done!")
                to_exit = True
                break  # This will break out of the while loop but NOT the for loop
            else:
                print("Not a valid score! Try again")
        except TypeError:
            print("Invalid input! Try again")
    if to_exit:
        break  # This will break out of the for loop

print(scores)
Sign up to request clarification or add additional context in comments.

7 Comments

I see now the the exit()/to_exit is what I was missing. On another forum someone said that I might not need the TypeError and I'm wondering if a ValueError might be better or something else. Or do you think TypeError is fine?
This is unnecessarily complicated. There's no code in this answer that would cause a TypeError exception. Why have 16 lines of (significant) code when you only need 5? Also, for dil in dil: is not best practice. Sure, it works, but seriously?
@user30902982 There is no need for any kind of exception handling here
The for dil in dil was a experiment I forgot to take out of my code. The code is actually for d in dil. It was more of me not paying attention when I copied the code onto here. As for exception handling, I've removed it.
@Ramrab You don't need 5 lines. You can do it in 1: scores = dict(zip(dils, (testscore for testscore in iter(lambda: input("Enter score: "), "q") if testscore in corr_input or print("Not a valid score!"))))
|
0

You just need a while loop that is limited by the number of available dil values and also account for user entering "q" (which would terminate the loop early).

PROMPT = "Enter score: "
INIT_SCORES = True
DIL = ["1:16", "1:32", "1:64", "1:128", "1:256"]
CORR_INPUT = {"+", "++-", "-", "+-", "-a", "A"}  # use a set here
# initialise the dictionary
# by doing this, if user enters "q" you'll easily be able
# to identify keys that do not have valid associated values
scores = {key: None for key in DIL} if INIT_SCORES else {}
dil = DIL.copy()

while dil and (testscore := input(PROMPT)) != "q":
    if testscore in CORR_INPUT:
        scores[dil.pop(0)] = testscore
    else:
        print("\aNot a valid score!")

print(scores)

Example 1:

Enter score: +
Enter score: +
Enter score: v
Not a valid score!
Enter score: +
Enter score: +
Enter score: +-
{'1:16': '+', '1:32': '+', '1:64': '+', '1:128': '+', '1:256': '+-'}

Example 2:

Enter score: ++-
Enter score: +
Enter score: q
{'1:16': '++-', '1:32': '+', '1:64': None, '1:128': None, '1:256': None}

Note:

This is destructive w.r.t the dil list. If you need that list for other purposes you'll need to take a copy and work with that

3 Comments

Thank you for the reply. I do need it later on for the second part which I will start on as soon as this part is complete. I was thinking of using the .item() as I need to iterate of the key-value pair till the last +/++- and print out that dil. But I'll take it one loop at a time!
@user30902982 I will edit this answer to make it non-destructive. Also, your additional requirement cannot be satisfied unless you ensure that either "+" or "++-" has been input
That is the idea, sometimes not all 5 dilutions will have a + or ++- score sometimes it's the first three of them and the fourth will be - or +- or -a as an example.

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.