Reputation: 9
I want to sort grades alphabetically in a function that are in tuples, such as:
sortGrades([('John Smith', 'C'), ('Adam Thomas', 'B'), ('Katie Johnson', 'A')])
and also, numerically, like this:
sortGrades([('John Smith', 54), ('Adam Smith', 54), ('Thomas King', 88)])
So it will sort the tuples by highest score and highest grade. The names should also be sorted alphabetically if there are two people with the same score.
So far my function looks like this:
def sortGrades(list):
return sorted(list, key=lambda x:(-x[1],x[0]))
However this does not seem to work when I sort grades (A, B, C), it returns a "TypeError: bad operand type for unary -: 'str'"
Any idea how to make it work for strings and integers at the same time?
Upvotes: 0
Views: 1552
Reputation: 214979
One option is to make a dict that translates notes to ints and pick values from that dict:
a = [('John Smith', 'B'), ('Adam Thomas', 'A'), ('Katie Johnson', 'C')]
b = [('John Smith', 54), ('Adam Smith', 54), ('Thomas King', 88)]
def sort_grades(lst):
notes = {'C':1, 'B':2, 'A':3}
return sorted(lst, key=lambda (x, y): (notes.get(y, y), x))
print sort_grades(a)
print sort_grades(b)
get(y, y)
basically means "if dicy[y] exists, return that, otherwise return y itself".
Upvotes: 0
Reputation: 14619
Try this, it's satisfactory for comparing a list that contains alpha grades OR a list that contains numerical grades.
def sortedGrades(some_contents):
def as_numeric(x): return (-x[1],x[0])
def as_alpha(x): return (-ord(x[1]), x[0])
sort_keys = { type(0): as_numeric,
type('A'): as_alpha,
}
if not some_contents:
return some_contents
sort_key = sort_keys[type(some_contents[0][1])]
return sorted(some_contents, key=sort_key)
Upvotes: 0
Reputation: 20938
In a similar way to what you wrote, I would do it like this:
return sorted(list, key=lambda x:(tuple(-ord(c) for c in x[1]), x[0]))
This basically negates all the characters in the string, so you can still sort in lexographic order.
Of course, since your case only has single-character strings, calling ord
once would work.
If you want for this to work with both strings and ints, then it's a bad idea. How do you compare 'A'
and 54
? It's better to have two versions of the function.
Upvotes: 1
Reputation: 251408
If all your grades are single uppercase letters, you could use key=lambda x: (-ord(x[1]), x[0]))
(sorting by the ASCII values of the characters).
Upvotes: 0