#python #function #if-statement #tuples
Вопрос:
У меня есть 3 группы результатов учащихся: группа_а, группа_в и группа_с
Каждая группа содержит список кортежей в следующем порядке: (номер студента,оценка).
Я хотел бы распечатать сообщение для каждого студента в зависимости от его оценки:
- Каждый студент в группе А : «Молодец, студент {}. Ваш счет был {}»
- Каждый студент в группе В : «Хорошая работа, студент {}. Ваш счет был {}»
- Каждый студент в группе C : «Привет, студент {}. Ваш счет был {}. Ты можешь сделать лучше, чем это».
В попытке добиться этого я объединил все 3 группы, прежде чем сортировать их по первому элементу кортежа.
all_groups = group_a group_b group_c
# take first element for sort
def takeFirst(elem):
return elem[0]
#using the 'takeFirst' function, sort tuple based on the first element
all_groups.sort(key=takeFirst)
#each tuple reflects (student number, score)
print(all_groups)
[(1, 29), (2, 54), (3, 52), (4, 50), (5, 30), (6, 57), (7, 56), (8, 47), (9, 51), (10, 55)]
Затем я напечатал сообщение для каждого студента в зависимости от их оценки.
collection4 = []
collection5 = []
collection6 = []
for number, pair1 in enumerate(all_groups):
# Unpack pair1: number, student_score
student_number, score1 = pair1
# print msg for each student. Attach every sentence into a 'collection' bucket.
if score1 >=60:
collection4.append('Well done student {}. Your score was {}.'.format(student_number, score1))
elif score1 >=50 and score1<=59:
collection5.append('Good work student {}. Your score was {}.'.format(student_number, score1))
else:
collection6.append('Hi student {}. Your score was {}. You can do better than this.'.format(student_number, score1))
Затем я объединил коллекцию 4, 5 и 6 в одно ведро.
totalcollection = collection4 collection5 collection6
Однако, когда я печатаю содержимое переменной «totalcollection», результаты не упорядочиваются в порядке возрастания числа учащихся.
Могу я узнать, как я могу решить эту проблему? Спасибо.
Ответ №1:
Проблема возникает здесь:
totalcollection = collection4 collection5 collection6
общая коллекция сначала добавит коллекцию 4, затем 5 и 6, однако предположим, что если студент с идентификатором 1 не попадет в коллекцию 4 и окажется в коллекции 6, то он будет добавлен в общую коллекцию после того, как все результаты в коллекции 4 и 5 уже были добавлены, что нарушит порядок.
Простое решение состоит в том, чтобы просто использовать одну коллекцию и добавить в нее все, чтобы результаты были упорядочены.
totalcollection = []
for number, pair1 in enumerate(all_groups):
# Unpack pair1: number, student_score
student_number, score1 = pair1
# print msg for each student. Attach every sentence into a 'collection' bucket.
if score1 >= 60:
totalcollection .append(
'Well done student {}. Your score was {}.'.format(student_number, score1))
elif score1 >= 50 and score1 <= 59:
totalcollection .append(
'Good work student {}. Your score was {}.'.format(student_number, score1))
else:
totalcollection .append('Hi student {}. Your score was {}. You can do better than this.'.format(
student_number, score1))
Ответ №2:
Вы отсортировали все по номеру студента. Затем вы создали подгруппы на основе результатов теста. В этот момент каждая подгруппа была отсортирована по номеру студента. Затем вы просто склеили подгруппы, основанные на результатах теста, вместе. Нет причин ожидать, что результирующая группа будет отсортирована по номеру учащегося-подгруппы были созданы в соответствии с другим атрибутом.
Вы можете упростить ситуацию, используя более значимые данные. Вместо необработанных кортежей рассмотрите более декларативные варианты, такие как namedtuple
, dataclass
, или attrs
класс. Например:
from collections import namedtuple
# The raw data.
raw_data = [(1, 29), (3, 52), (2, 40), (4, 50), (7, 70), (5, 65), (6, 17)]
# Create meaningful objects holding that information.
TestResult = namedtuple('TestResult', 'student_number score')
test_results = [TestResult(*tup) for tup in raw_data]
# Tuples automatically sort by checking their first elements first.
test_results.sort()
И если вы хотите генерировать сообщения, просто напишите функцию, принимающую
TestResult
и возвращающую сообщение. Не смешивайте эту
логику с другими проблемами, такими как повторение всех результатов теста.
def result_message(tr):
fmt = (
'Well done student {}. Your score was {}.' if tr.score >= 60 else
'Good work student {}. Your score was {}.' if 50 <= tr.score <= 59 else
'Hi student {}. Your score was {}. You can do better than this.'
)
return fmt.format(tr.student_number, tr.score)
Когда вы хотите распечатать, это легко, и у вас все равно будет нужный заказ:
for tr in test_results:
print(result_message(tr))
Комментарии:
1. Спасибо тебе, @FMc. Приятно знать другой способ решения этой проблемы.