Home > Back-end >  Calculating average of top 4 int values out of 5 values in a sub-list. (2 values are same)
Calculating average of top 4 int values out of 5 values in a sub-list. (2 values are same)

Time:02-17

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)
  • Related