Reputation:
I have a dictionary where the keys are names and the values are lists of up to 3 integers (these are the scores of the named people):
classScores={
'Bob':[1, 6, 3],
'Jim':[6, 10, 3],
'Fred':[0, 2]
}
I need to print it sorted by the average of the scores (highest first). I have created a working code to do this:
classAverages={}
for student in classScores:
classAverages[student]=sum(classScores[student])/len(classScores[student])
for student in sorted(classAverages, key=classAverages.get, reverse=True):
print(student, "Average:", sum(classScores[student])/len(classScores[student]))
However, I feel this is inefficient as it uses 2 for
loops so has to go through every student twice. I am therefore looking for suggestions that incorporate the sorting into the 2nd loop (presumably into its sorted function).
UPDATE: I've gone with a lambda, but I have defined it before the for
loop so that I can also use it to print the averages:
classAverages=lambda student: sum(classScores[student]) / len(classScores[student])
for student in sorted(classScores, key=classAverages, reverse=True):
print(student, "Average:", classAverages(student))
Upvotes: 2
Views: 2561
Reputation: 1122502
You can calculate the average per student in the key
function:
for student in sorted(classScores, key=lambda k: sum(classScores[k]) / len(classScores[k]), reverse=True):
Using two loops is only marginally less efficient however; you only increased the fixed cost per student to determine the order. You missed an opportunity to re-use that average in your second loop when displaying the averages:
classAverages={}
for student in classScores:
classAverages[student] = sum(classScores[student]) / len(classScores[student])
for student in sorted(classAverages, key=classAverages.get, reverse=True):
print(student, "Average:", classAverages[student])
You could loop over the dictionary items in a generator expression to calculate the averages, sort on those averages, and then display the calculated average all in one operation:
student_averages = ((sum(scores) / len(scores), s) for s, scores in classScores.items())
for average, student in sorted(student_averages, reverse=True):
print(student, "Average:", average)
The generator produces the data in (average, student)
pairs to ease sorting (we now don't need a key
to pick out the second value).
Upvotes: 4