Say I have these students with their corresponding grades and weights:
grades = {'terri': [55,90,10], 'kerry': [88,66,77], 'sherry': [70, 90,10], 'jerry': [90, 60, 90], 'hari': [0, 100, 97]}
weights = [20,40,40]
I then want to create a function that finds the weighted average
def final_grade(gr,wghts):
"""
input: A dict (with students as keys & a list of length n) and a set of weights for each assignment (length n)
output: list of pairs (stu_nam/grade)
"""
its=range(len(wghts))
weigh_grad={}
for stu in gr:
for grads in gr[stu]:
for i in its:
if stu not in weigh_grad:
weigh_grad[stu]=(gr[stu][i]*wghts[i])/100
else:
weigh_grad[stu] =(gr[stu][i]*wghts[i])/100
return weigh_grad
final_grade(grades,weights)
My output is:
>>> {'terri': 153.0,'kerry': 224.40000000000003,'sherry': 162.0,'jerry': 234.0,'hari': 236.39999999999998}
Use the example of Terri. Their weighted average is actually 51. It has trebled. The same occured to Kerry and so on. All of my outputs are treble what I expected.
CodePudding user response:
Every key in a dictionary is unique. You are iterating over each key too many times and writing over the value stored at that key.
Code:
grades = {'terri': [55,90,10], 'kerry': [88,66,77], 'sherry': [70, 90,10], 'jerry': [90, 60, 90], 'hari': [0, 100, 97]}
weights = [20,40,40]
def final_grade(gr,wghts):
"""
input: A dict (with students as keys & a list of length n) and a set of weights for each assignment (length n)
output: list of pairs (stu_nam/grade)
"""
weigh_grad={}
for stu, grads in gr.items():
weigh_grad[stu] = 0.0
for idx, g in enumerate(grads):
weigh_grad[stu] = g * wghts[idx] / 100
return weigh_grad
Output:
{'terri': 51.0, 'kerry': 74.8, 'sherry': 54.0, 'jerry': 78.0, 'hari': 78.8}
CodePudding user response:
This is the problem:
for grads in gr[stu]
Use this instead, your code is running three more times because of the extra for loop:
def final_grade(gr,wghts):
"""
input: A dict (with students as keys & a list of length n) and a set of weights for each assignment (length n)
output: list of pairs (stu_nam/grade)
"""
its=range(len(wghts))
weigh_grad={}
for stu in gr:
s = 0
for i in its:
s =(gr[stu][i]*wghts[i])/100
weigh_grad[stu]=s
return weigh_grad
CodePudding user response:
A possible solution is:
def final_grade(grades_per_student, wghts):
"""
input: A dict (with students as keys & a list of length n) and a set of weights for each assignment (length n)
output: list of pairs (stu_nam/grade)
"""
total_weight = sum(wghts)
weighted_averages = {}
for student, student_grades in grades_per_student.items():
weighted_averages[student] = 0
for index, grade in enumerate(student_grades):
weighted_averages[student] = grade * wghts[index] / total_weight
return weighted_averages
CodePudding user response:
grades = {'terri': [55,90,10], 'kerry': [88,66,77], 'sherry': [70, 90,10], 'jerry': [90, 60, 90], 'hari': [0, 100, 97]}
weights = [20,40,40]
di = {}
for e in grades:
for i in range(len(weights)):
if e not in di:
di[e] = grades[e][i] * weights[i]/100
else:
di[e] = grades[e][i] * weights[i]/100
print(di)
Out:
{'terri': 51.0, 'kerry': 74.8, 'sherry': 54.0, 'jerry': 78.0, 'hari': 78.8}
CodePudding user response:
You can use zip
and sum
.
def final_grade(gr,wghts):
for k,v in gr.items():
gr[k] = sum((a*b)/100 for a,b in zip(wghts, v))
return gr
Output:
>>> grades = {'terri': [55,90,10], 'kerry': [88,66,77], 'sherry': [70, 90,10], 'jerry': [90, 60, 90], 'hari': [0, 100, 97]}
>>> weights = [20,40,40]
>>> final_grade(grades,weights)
{'terri': 51.0, 'kerry': 74.8, 'sherry': 54.0, 'jerry': 78.0, 'hari': 78.8}