У меня есть массив с идентификатором имени и отметки.

И я хочу вычислить итоговую оценку и выполнить операцию, когда придет следующий студент.

Я использую приведенный ниже код, но мне нужно окончательно вызвать метод после завершения операции.

Есть ли лучший способ, чем этот, без вызова метода после цикла.



student_id_name_marks = [
    (1,"John",23),
    (2,"Paul",30),
    (2,"Paul",32),
    (2,"Paul",40),
    (3,"Doe",43),
    (3,"Doe",42),
    (4,"Jerry",45)
]


current_user_id = None
total_marks = None
for marks in student_id_name_marks:
    if current_user_id == marks[0]:
        total_marks += marks[2]
    else:
        if total_marks:
            calculate_average(total_marks)
        total_marks = marks[2]
        current_user_id = marks[0]

if total_marks:
            calculate_average(total_marks)
0
wulfnb 24 Июн 2019 в 15:27

3 ответа

Лучший ответ

Я бы сохранил их в словаре

from collections import defaultdict
marks = defaultdict(list)
for id, name, mark in student_id_name_marks:
     marks[name].append(mark)  # could use the id instead of name as key

Затем вы можете просто рассчитать среднее значение для каждого человека, что по-прежнему является лучшим способом сделать это.

for key, val in marks.items():
     calculate_average(val) # key will be the persons name if you need it

В качестве альтернативы рассмотрите возможность создания класса Person, который содержит идентификатор, имя и список отметок. затем ведите список этих объектов и работайте над объектом person, как вам нужно

class Person:
     def __init__(self, id, name):
          self.id = id
          self.name = name
          self.marks = []
    def add_mark(mark):
          self.marks.append(mark)
    def average_mark():
          return sum(self.marks) / len(self.marks)
2
Sayse 24 Июн 2019 в 12:43

Вы можете добавить запись в список и игнорировать ее:

student_id_name_marks = [    
    (1,"John",23),    
    (2,"Paul",30),    
    (2,"Paul",32),    
    (2,"Paul",40),    
    (3,"Doe",43),    
    (3,"Doe",42),    
    (4,"Jerry",45),    
    (-1,"EOF",0),     
]    

current_user_id = None    
total_marks = None        
for marks in student_id_name_marks:    
    if current_user_id == marks[0]:    
        total_marks += marks[2]        
    else:                              
        if total_marks:                
            print(current_user_id, total_marks)    
        total_marks = marks[2]    
        current_user_id = marks[0]

Производит :

1 23
2 102
3 85
4 45
0
Zach Thompson 24 Июн 2019 в 14:08

Вы можете преобразовать свой список в фрейм данных Pandas для более простых и быстрых вычислений:

student_id_name_marks = [
    (1,"John",23),
    (2,"Paul",30),
    (2,"Paul",32),
    (2,"Paul",40),
    (3,"Doe",43),
    (3,"Doe",42),
    (4,"Jerry",45)
]

df= pd.DataFrame(student_id_name_marks)
df.columns = ['id', 'Name', 'Mark']

   id   Name  Mark
0   1   John    23
1   2   Paul    30
2   2   Paul    32
3   2   Paul    40
4   3    Doe    43
5   3    Doe    42
6   4  Jerry    45

# We groupby students to get each student's average mark
students_mean = df.groupby('id')['Mark'].mean()

# We compute the average mark
students_mean .mean()

Выход:

36.125
2
vlemaistre 24 Июн 2019 в 14:02