0

So I'm mostly looking for advice on how I could tidy up my code. I've got a class that's got an integer instance variable, x \in [0, 100]. I want to assign each instance a letter grade (instance variable g) based on its x value. Is there a better/more concise way of doing this than using lots of if, elif, else statements?

if self.x < 25:
   self.g = 'f'
elif self.x < 50:
   self.g = 'e'
elif self.x < 70:
   self.g = 'd'
elif self.x < 80:
   self.g = 'c'
elif self.x < 90:
   self.g = 'b'
else:
   self.g = 'a'
LegendWK
  • 184
  • 9

4 Answers4

1

You can use pandas for this:

import pandas as pd
s = pd.Series([2, 41, 61, 83])
pd.cut(s, [0, 25, 50, 70, float("inf")], labels=['a', 'b', 'c', 'd'], retbins=True, right=True)

# 0    a
# 1    b
# 2    c
# 3    d

Without a library (credits):

class RangeDict(dict):
    def __getitem__(self, item):
        if not isinstance(item, range):
            for key in self:
                if item in key:
                    return self[key]
            raise KeyError(item)
        else:
            return super().__getitem__(item)

rng = RangeDict({range(0, 25): 'f', range(25,50): 'e'})
val = 21
print(rng[val])
# f
Andreas
  • 8,694
  • 3
  • 14
  • 38
0

Can just go with a loop, nothing too fancy.

letters = 'fedcba'
grades = [25, 50, 70, 80, 90, 101]

x = 75

for letter, grade in zip(letters, grades):
    if x < grade:
        g = letter
        break
Steven Summers
  • 5,079
  • 2
  • 20
  • 31
0

You could just use a dict and for loop.

grade_limits = {25: 'f', 50: 'e', 70: 'd', 80: 'c', 90: 'b'}
for limit, grade in grade_limits.items():
    if self.x < limit:
        self.g = grade
        break
else:
    self.g = 'a'

This is a bit more concise and has no upper limit for 'a'.

Axe319
  • 4,255
  • 3
  • 15
  • 31
0

Same as your example, this works for any number, no matter how big or if negative or if float:

grades, steps = "abcde", [90,80,70,50,25]
self.g = next((grade for grade, step in zip(grades, steps) if self.x >= step), "f")

It's shorter, but I can't say if I'd prefer it to your original elif solution, since that's by far the most expressive/readable in my opinion.

Jeronimo
  • 2,268
  • 2
  • 13
  • 28