Convert numbers to grades in python list

30,375

Solution 1

Define a function that takes a mark and returns a human readable representation, you can use larsmans's expression or this one:

def grade(i):
    if i<40: return "Fail"
    if i>75: return "A++"
    if i>50: return "A"

Use string.format to format each entry and map to iterate over all of them:

li = map(lambda x: "{0} - {1}".format(x, grade(x)), s)

The resulting list now contains strings in the desired format.

for i in li: print i

# output

50 - None
62 - A
15 - Fail
76 - A++
57 - A
97 - A++
82 - A++
99 - A++
45 - None
23 - Fail

Solution 2

Forget lambda, forget filter; the following does the grading in one expression, assuming there's a B grade between A and "fail".

["fail" if g < 40 else "B" if g < 60 else "A" if g < 75 else "A++" for g in s]

You can zip the result of this with s to get marks and grades in one list.

Solution 3

s = [50,62,15,76,57,97,82,99,45,23]
x = dict([(a, 'A++' if a>75 else 'A' if a>55 else 'F') for a in s])

print x

{97: 'A++', 45: 'F', 99: 'A++', 76: 'A++', 82: 'A++', 15: 'F', 50: 'F', 23: 'F', 57: 'A', 62: 'A'}

Use x.items() to do filter, for example

filter(lambda x: x[1] == 'A', x.items())

the result is

[(57, 'A'), (62, 'A')]

Solution 4

You can write your own filter-like function:

def filter_n(n, f, lst):
    result = tuple([[] for i in range(n)])
    for elem in lst:
        result[f(elem)].append(elem)
    return result

The answer is now looking as following:

grades = filter_n(3, lambda x: (x < 40) * 0 +
                               (60 < x <= 75) * 1 +
                               (75 < x) * 2, s)
Share:
30,375
sam
Author by

sam

Updated on July 05, 2022

Comments

  • sam
    sam almost 2 years

    I have a list which has the number of marks students have.

    s = [50,62,15,76,57,97,82,99,45,23]
    

    I want to grade students according to marks:

    <40 - Fail
    >50 - A Grade
    >75 - A++ Grade
    

    I can do this with iterating loops or I can find every list using lambda. for example :

    >>> filter(lambda x:x>=50, s)
    [50, 62, 76, 57, 97, 82, 99]
    

    But, in the filter, I can work with only one function at a time (for example : marks greater than 50). Is there way where I can use filter and lambda and get required result in one line? Expecting the output as marks with grade. (ex : 50 - A, 62 - A, 76 - A++ ...)

  • rplnt
    rplnt over 12 years
    Or you can use map, map(lambda x: (x, 'F' if x<40 else 'A++' if x>70 else 'A'), s). Or just lose the (x, (and ) of course) if you want just grades. List is ordered so you can match it later on.
  • yurisich
    yurisich almost 12 years
    You comprehension is at 78 characters. You get free line breaks in them. I know it goes against Google Python style rules, but I prefer to break them over multiple lines, possibly at the end of each else.
  • Fred Foo
    Fred Foo almost 12 years
    @Droogans: I'm not aware of Google style rules, but in a practical program I would indeed put some linebreaks in. stackoverflow.com/a/5809080/166749
  • Chris Wesseling
    Chris Wesseling over 11 years
    2 scopes on one line where the x name is something different. Not very different from other answer, so if you had the edit privilege, an edit might have been a better fit than an answer.