assigning grade on basis of range:
def getGrade(size):
grade =''
if size <= 32:
grade = 'p4'
elif size > 32 and size <=64:
grade = 'p6'
elif size > 64 and size <= 128:
grade = 'p10'
elif size > 128 and size <= 256:
grade = 'p15'
elif size > 256 and size <=512:
grade = 'p20'
elif size > 512 and size <= 1024:
grade = 'p30'
elif size > 1024 and size <= 2048:
grade = 'p40'
......
Problem is need to add 20 more check so is there any way to do better than this approach.
Due do the ranges being contiguous, you can avoid repeating the lower bound.
Putting all the ranges in tuples can save you some typing (if the first range does not go down to negative infinity, consider adding the tuple (0, None)
before all others:
def getGrade(size):
grades = (
(32, 'p4'),
(64, 'p6'),
(128, 'p10'),
...
)
for maxVal, grade in grades:
if size <= maxVal:
return grade
Test:
>>> getGrade(45)
'p6'
>>> getGrade(100)
'p10'
Efficiency:
If the grades
list is really long, you can achieve better runtime than scanning every item. Since the list is sorted, you can use bisect
, by replacing the for loop:
for maxVal, grade in grades:
if size <= maxVal:
return grade
with:
index = bisect.bisect(grades, (size, ))
if index < len(grades):
return grades[index][1]
The number of steps is reduced (in the worst case) from N (the length of grades
) to log2(N).
A brute force approach would be simple as
all_grades = [i for i in chain(repeat('p4',32),repeat('p6',64-32) and so on)]
then you can get grade as
grade = all_grades[size-1]
it may require space if list is exponential