Как я могу печатать строки в порядке возрастания индекса в кортеже

#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. Приятно знать другой способ решения этой проблемы.