Home > Back-end >  Use fewer if statements to test in which interval a given integer belongs
Use fewer if statements to test in which interval a given integer belongs

Time:01-06

m = int(input("How many marks on the test? (/100)"))
if m >= 10 and m < 20:
    print("Grade 1.")
elif m >= 20 and m < 30:
    print("Grade 2.")
elif m >= 30 and m < 40:
    print("Grade 3.")

The code above is for grading a test score out of 100, with grades 1 to 9, 9 being the highest at 90 or higher marks.

How could I do the same code but with less if/elif statements?

CodePudding user response:

Assuming the grades are evenly spaced and directly proportional to the score, you can just do an integer division, a//b.

But if the scale isn’t linear, I suggest doing it by looping through a list of thresholds:

grades = [
    30, # 1 (lowest passing grade)
    50, # 2
    60, # 3
    70, # 4
    75, # 5
    # more grades...
]

score = int(input("score"))

for grade, threshold in enumerate(grades):
    if score < threshold:
        print(f"grade: {grade}")
        break
else:
    # this happens if the score is
    # higher than the highest grade
    # threshold in the list (75 in
    # this case)
    print("Wow, very high score!")

CodePudding user response:

Yevhen's solution is undoubtedly the best for this particular scenario with uniform boundary sizes. Although it does get 100/100 wrong (grade 10) if the upper limit is supposed to be grade 9.

If things were a little different (i.e. grade 3 spanned from 30 to 50) then you could look at an approach like below:

m = int(input("How many marks on the test? (/100)"))

grades = {0: {"lb": 0, "ub":10},
          1: {"lb": 10, "ub":20},
          2: {"lb": 20, "ub":30}, 
          3: {"lb": 30, "ub": 40},
          4: {"lb": 40, "ub": 50},
          5: {"lb": 50, "ub": 60},
          6: {"lb": 60, "ub": 70},
          7: {"lb": 70, "ub": 80},
          8: {"lb": 80, "ub": 90},
          9: {"lb": 90, "ub": 101},
          }

for grade, bounds in grades.items():
    if m >= bounds["lb"] and m < bounds["ub"]:
        print(f"Grade {grade}")
        break

In this instance, the dictionary as above could be auto-generated by:

grades = {}
for grade in range(0, 10):
    grades[grade] = {"lb": grade*10, "ub": (grade 1)*10}
grades[9]["ub"] = 101  # The correction to avoid grade 10 if mark is 100

edit: Should probably also point out the handy thing about this is you can name the main key whatever you want, grades A*, A, B , B, B- etc? No problem.

For more complex use cases, you could even tack on additional key-val pairs to different things, even different method handles, for further processing.

CodePudding user response:

I did it this way;

m = 56
# gradeDict = {'score':'grade'}
gradeDict = {10:1,
             20:2,
             30:3,
             40:4,
             50:5,
             60:6,
             70:7,
             80:8,
             90:9,
             100:9}


for k in gradeDict.items():
    if m<k[0]:
        print("score:", k[1]-1)
        break
        

This is the output;

score: 5

CodePudding user response:

If you want to do it with one print statement then you can do it like this..

Note : Code only reduce print statements not conditions.

m=int(input("How many marks on the test? (/100)"))
print("Grade 1." if m>=10 and m<20 else "Grade 2." if m>=20 and m<30 else "Grade 3." if m>=30 and m<40 else "Grade4.")
  • Related