Given the following list:
student_marks = [['Name', ['A','B','C','D','E']],
['Ankit', [41, 34, 45, 55, 63]],
['Aravind',[42, 23, 34, 44, 53]],
['Lakshay',[32, 23, 13, 54, 67]],
['Gyan', [23, 82, 23, 63, 34]],
['Pranav', [21, 23, 25, 56, 56]]
]
If considering the top 4 subjects of a student, I am trying to find who scored the highest percentage of marks (Average of top 4 marks). We need to compare top 4 marks average of each student and find out who has the best percentage.
This is what i did:
best_four_marks = []
for i in student_marks[1:]:
student_name = i[0]
count_1 = 0
summ_1 = 0
for j in i[1]:
if j > min(i[1]):
count_1 = 1
summ_1 = j
avg = summ_1/count_1
best_four_marks.append([avg,student_name])
The problem here is that one of the students, i.e. Gyan has 2 values which are the same i.e. 23 marks in both subject A and subject C. I have instructed the compiler to ignore the worst mark to calculate the top 4 subjects percentage for every student. In Gyan's iteration, it completely ignores the 2 lowest values out of 5 subjects. I wanted to include one of them as we need top 4 subject's percentage.
Looking forward to hearing your feedback! Thanks.
CodePudding user response:
You can solve the problem by subtracting only the lowest score from the overall sum.
best_four_marks = []
for i in student_marks[1:]:
student_name = i[0]
summ_1 = sum(i[1]) - min(i[1])
count_1 = len(i[1])-1
avg = summ_1/count_1
best_four_marks.append([avg,student_name])
CodePudding user response:
student_marks = [
['Name', ['A','B','C','D','E']],
['Ankit', [41, 34, 45, 55, 63]],
['Aravind',[42, 23, 34, 44, 53]],
['Lakshay',[32, 23, 13, 54, 67]],
['Gyan', [23, 82, 23, 63, 34]],
['Pranav', [21, 23, 25, 56, 56]]
]
avg_marks = {}
for marks in student_marks[1:]: # ignore first entry
student = marks[0]
top_4_marks = sorted(marks[1], reverse=True)[:-1]
total_of_top_4_marks = sum(top_4_marks)
avg_marks[student] = total_of_top_4_marks/4
avg_marks
output
{'Ankit': 51.0,
'Aravind': 43.25,
'Lakshay': 44.0,
'Gyan': 50.5,
'Pranav': 40.0}
CodePudding user response:
Might be not the cleanest way, but I would do it with sorted()
Something like this...
for student in student_marks[1:]:
student_name = student[0]
grades_count = len(student[1]) - 1
grades = sorted(student[1][1:])
student_average = 0
for grade in grades:
student_average = student_average grade
student_average = student_average / grades_count
best_four_marks.append([student_name, student_average])
I would avoide the second loop, by just using
student_average = sum(grades) / grades_count
CodePudding user response:
Perhaps this solution is highly readable and easy to alter
student_marks = [['Name', ['A', 'B', 'C', 'D', 'E']],
['Ankit', [41, 34, 45, 55, 63]],
['Aravind', [42, 23, 34, 44, 53]],
['Lakshay', [32, 23, 13, 54, 67]],
['Gyan', [23, 82, 23, 63, 34]],
['Pranav', [21, 23, 25, 56, 56]]
]
output = []
for student in student_marks:
student_name = student[0]
list_marks = student[1]
# Check if string exists in the mark list
if any(isinstance(element, str) for element in list_marks):
continue
list_marks = sorted(list_marks, reverse=True)[:-1] # remove the lowest mark
average_mark = sum(list_marks) / len(list_marks)
output.append([student_name, average_mark])
CodePudding user response:
Because of you want to get average of 4 out of 5 this will be better code for each student
def getBest4Average(listScore):
return (sum(listScore) - min(listScore))/4
getBest4Average([20, 30, 10, 50, 60])
result:
40.0
If you want a version which calc (n-1) out of n
def getBestAverage(listScore):
size = len(listScore)
return (sum(listScore) - min(listScore))/(size - 1)
if you want n best out of >n elements list, if m is small this method will have better performance
def popmax(l):
m = max(l)
l.remove(m)
return m
def GetNBestAverage(listScore, n):
best = []
for i in range(0, n):
best.append(popmax(listScore))
return average(best)