0

I have the following set of rules for grading system

if 25 < score <= 30, grade = A. 
if 20 < score <= 25, grade = B. 
if 15 < score <= 20, grade = C. 
if 10 < score <= 15, grade = D. 
if 5 < score <= 10, grade = E. 
if 0 <= score <= 5, grade = F. 

so I have to write a function which takes score as parameter and returns letter grade. So I can do this using selections(if, else). But I want to do it in different manner. for instance I want to declare a dictionary like below:

gradeDict = {
    'A': [26, 27, 28, 29, 30],
    'B': [21, 22, 23, 24, 25],
    'C': [16, 17, 18, 19, 20],
    'D': [11, 12, 13, 14, 15],
    'E': [6, 7, 8, 9, 10],
    'F': [0, 1, 2, 3, 4, 5] 
}

so while checking the score with values I want to return the key

In python I've learned something like dict.get(term, 'otherwise') but it will give you the values. Is there any other mechanism that does the opposite, ie: if we can pass the value in the get method it will return the key?

Imtiaz Ahmed
  • 123
  • 3
  • 12

2 Answers2

1

The bisect standard library offers an elegant solution to problems like this one. In fact, grading is one of the examples shown in the docs.. Here is an adaption of the example modeled on OP's grading curve:

Example:

from bisect import bisect_left

def grade(score, breakpoints=[5, 10, 15, 20, 25], grades='FEDCBA'):
    i = bisect_left(breakpoints, score)
    return grades[i]

[grade(score) for score in [1, 5, 8, 10, 11, 15, 17, 20, 22, 25, 26]]

Output:

['F', 'F', 'E', 'E', 'D', 'D', 'C', 'C', 'B', 'B', 'A']

rhurwitz
  • 2,557
  • 2
  • 10
  • 18
0

Funny thing is that you don't even need a dictionary for this, just an array. Ofc you can do it in a dictionary way style by declaring the following dict:

gradeDict = {
        1:'F',
        2:'E',
        3:'D',
        4:'C',
        5:'B',
        6:'A'
    }

This dict seems to be useless since it's just an ordered list of indexes 1,2,3... You can transform it: grates_arr = ['F', 'E', 'D', 'C', 'B', 'A']

But how can I get the letter that I need? you may ask. Simple, divide the score by 5. 21 // 5 means 4. grates_arr[21//5] is 'B'. 2 more particular cases: when the score divides 5 means you have to subtract 1 because for example 25 // 5 means 5 but grates_arr[5] is A not B. when score is 0 do not subtract.

Noxium
  • 61
  • 4
  • In your approach a string of all letter grades 'FEDCBA'[score // 5] would do the same. But I want that dictionary approach. – Imtiaz Ahmed Mar 29 '21 at 11:47
  • letterGrade = 'FEDCBA'[(score - 1) // 5 if score > 0 else 0] this is pretty much what you suggested. But Can you help me with the way I asked the question for? – Imtiaz Ahmed Mar 29 '21 at 12:07
  • well, if you really want to use that dictionary which seems to be inefficient take a look here: https://stackoverflow.com/questions/8023306/get-key-by-value-in-dictionary – Noxium Mar 29 '21 at 12:13
  • mydict = {'george': 16, 'amber': 19} print(list(mydict.keys())[list(mydict.values()).index(16)]) have a look at it this is pretty much close to what I want. But in my case the value is a list. is there any way to pass the score in index which will then iterate through the list of values of the dict and will eventually return the key? – Imtiaz Ahmed Mar 29 '21 at 15:49