Home > OS >  Alternatives of repeatedly using elif statements
Alternatives of repeatedly using elif statements

Time:09-20

Im trying to return the 'students' grades according to what they got on python. I used a bunch of elif statements but i dont feel like this is efficient. I was wondering if there are any other ways i can present this as? possibly smaller. Ive attempted using for loops and dictionaries, but im not getting it, maybe cuz i dont understand dictionaries well loll

def grade_select(grade):
    if grade <  40: return "D-"
    elif grade <= 40 and grade < 45: return "D"
    elif grade <= 45 and grade < 50: return "D "
    elif grade <= 50 and grade < 55: return "C-"
    elif grade <= 55 and grade < 60: return "C"
    elif grade <= 60 and grade < 65: return "C "
    elif grade <= 65 and grade < 70: return "B-"
    elif grade <= 70 and grade < 75: return "B"
    elif grade <= 75 and grade < 80: return "B "
    elif grade <= 80 and grade < 85: return "A-"
    elif grade <= 85 and grade < 90: return "A" 
    elif grade >= 90: return "A "

CodePudding user response:

since you return when a condition is matched, you do not need to use elif just if.

moreover, the previous condition eliminates the need of checking if the value is "between".

def grade_select(grade):
    if grade < 40: return "D-"
    if grade < 45: return "D"
    if grade < 50: return "D "
    if grade < 55: return "C-"
    if grade < 60: return "C"
    if grade < 65: return "C "
    if grade < 70: return "B-"
    if grade < 75: return "B"
    if grade < 80: return "B "
    if grade < 85: return "A-"
    if grade < 90: return "A" 
    return "A "

an alternative would be to declare a dictionary and calculate where the grade fits.

grades = { 40: "D-", 45: "D", 50: "D ", 55: "C-", 60: "C", 65: "C ", 70: "B-", 75: "B", 80: "B ", 85: "A-", 90: "A", 100: "A " }

def grade_select(grade):
    grade = (grade // 5 * 5)   5

    if grade < 40:
        grade = 40
    elif grade > 90:
        grade = 100

    return grades[grade]

CodePudding user response:

You can use a dictionary to store the range and it's according grade value:

def grade_select(grade):
    dct = {
        range(0, 40): "D-",
        range(40, 45): "D",
        range(45, 50): "D ",
        ...
        range(90, 100   1): "A "
    }
    dct = {g: m for r, m in dct.items() for g in r}
    return dct[grade]

CodePudding user response:

Well, your condition is kinda weird, because

elif grade <= 40 and grade < 50

has no sense (if grade <= 40 then grade < 50 of course)

But I think you wanna write something like this:

if 40 <= grade < 50:
    pass

You can use syntax above, it could make it a little bit better. Also, you can check this article

CodePudding user response:

I guess using dictionary is the best way

def grade_select(grade):
    d = {
        'D-':range(0,40),
        'D':range(45,50),
        'D ':range(50,55),
        'C-':range(55,60) #, etc.
    }

    return [k for k,v in d.items() if grade in v]

CodePudding user response:

Here's the fastest version that calculates an index based on the grade value. This method only works if your grade ranges are all five wide.

_lettergrades = ['D-', 'D', 'D ', 'C-', 'C', 'C ', 'B-', 'B', 'B ', 'A-', 'A', 'A ']

def grade_select(grade):  
    return _lettergrades[(max(min(grade, 90), 35) - 35) // 5]

If your ranges weren't consistently five wide you could use bisect.bisect_right to get an index for the letter grade. The search uses bisection, which should be faster than a linear search. (The lists _thresholds and _lettergrades are global to avoid recreating them for every call to grade_select().)

from bisect import bisect_right
    
_thresholds = [40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90]
_lettergrades = ['D-', 'D', 'D ', 'C-', 'C', 'C ', 'B-', 'B', 'B ', 'A-', 'A', 'A ']

def grade_select(grade):
    return _lettergrades[bisect_right(_thresholds, grade)]

Note: I doubt speed matters as much as clarity here. For clarity I like Paulo Pereira's answer best.

  • Related