Сравнение результатов из словаря

#python #list #if-statement #for-loop #dictionary

#python #Список #if-оператор #for-цикл #словарь

Вопрос:

То, что я пытаюсь сделать, это прочитать из текстового файла, который содержит список имен, соответствующих трем оценкам. В программе файл считывается и заносится в один словарь. Из словаря я должен сравнить результаты и вывести, какой из них самый высокий, самый низкий и т.д. Я пытаюсь использовать цикл for, но продолжаю сталкиваться с несколькими проблемами. На этот раз я столкнулся с ошибкой типа 1 при попытке компиляции. Какой наилучший способ сравнить значения словаря в цикле for? Есть предложения?

Вот то же самое из текстового файла:

 Brian,94,89,92
Rachel,100,90,65
Jon,67.5,95,100
Brit,0,78,80
Greg,65,100,78
Andrea,55.5,67,79
  

Вот мой код на данный момент: вывод ошибки внизу.

 def examMod ():

    students = {}

    infile = open("studentGrades.txt","r")
    for aline in infile:
        key, val1, val2, val3 = aline.split(',')
        students[key] = float(val1), float(val2), float(val3)

    for z in students.keys():   
        for x in students.items():
            if students[1] > students[2] amp; students[1] > students[3]:
                print("For %s test 1 is the highest scored." % z)
            elif students[2] > students[1] amp; students[2] > students[3]:
                print("For %s test 2 is the highest scored." % z)
            elif students[3] > students[1] amp; students[3] > students[2]:
                print("For %s test 2 is the highest scored." % z)


Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    examMod()
  File "E:PythonLibidlelibredoMidterm.py", line 12, in examMod
    if students[1] > students[2] amp; students[1] > students[3]:
KeyError: 1
  

Комментарии:

1. Можете ли вы включить ошибку? Какую трассировку стека он выводит?

2. Добавил это в now. Забыл добавить, что, вероятно, помогло бы правильно?

Ответ №1:

Я не думаю, что вы вытаскиваете детали, которые, по вашему мнению, есть. Я бы дважды проверил, что keys() и items() делать.

Ваш первый намек — это KeyError: 1 . Это означает, что вы проверили в словаре наличие ключа 1 , но он не существует (сбивает с толку, но это не тип ошибки 1, просто значение 1 является причиной ошибки). Просматриваем возвращенную строку: if students[1] > students[2] amp; students[1] > students[3]: она будет исходить от студентов. Это означает, что students это словарь, а 1 в нем нет ключа.

Во-вторых, вы неправильно используете эти циклы. Хороший совет для проверки того, как вы его используете, — вызвать функцию с помощью инструкции print. Например.

 for z in students.keys():
    for x in students.items():
        print(z, x)
        # Then comment out the rest of this loop
  

Основываясь на первых трех строках приведенных вами примеров данных, это вернет:

 Brian ('Brian', (94.0, 89.0, 92.0))
Brian ('Rachel', (100.0, 90.0, 65.0))
Brian ('Jon', (67.5, 95.0, 100.0))
Rachel ('Brian', (94.0, 89.0, 92.0))
Rachel ('Rachel', (100.0, 90.0, 65.0))
Rachel ('Jon', (67.5, 95.0, 100.0))
Jon ('Brian', (94.0, 89.0, 92.0))
Jon ('Rachel', (100.0, 90.0, 65.0))
Jon ('Jon', (67.5, 95.0, 100.0))
  

Почему это? Поскольку вы перебираете имя каждого учащегося с помощью students.keys() и для каждого учащегося, вы затем снова перебираете каждого учащегося, предоставляя ключ и значение с помощью students.items() . Я бы потратил немного времени на выяснение этого, потому что на самом деле это самая большая часть вашей проблемы.

Причина, по которой вы получаете ошибку ключа? Потому что вы проверяете только исходный словарь с помощью students[...] .

Как только вы разберетесь с этим, вы подойдете к третьей проблеме. IndexError потому что вы обращаетесь к 4-му элементу массива оценок из 3 элементов с помощью whatever_you_are_checking[3] . Потому что первым элементом массива является индекс 0 , вторым 1 , третьим 2 . Компьютерщики считают от 0.

Итак. В конечном счете, вам нужно:

  1. Только один цикл для студентов. Вам нужно проверить каждое имя только один раз
  2. Смотреть на результаты, а не на массивы учащихся, когда вы выполняете свои проверки
  3. Проводите свои сравнения с base-0, а не с base-1

В принципе, что-то вроде:

 for z in students.keys():
    if students[z][0] > students[z][1] and students[z][0] > students[z][2]:
        print("...")
  

Следующее не является существенным, но я хочу показать лишь некоторые вещи, потому что python действительно классный.

  • Как вы выяснили в своем split заявлении, вы можете разбить возвращаемые значения из списков или кортежей на несколько переменных за один раз. Вы могли бы использовать это, чтобы упростить работу вашего цикла for:

     for student_name, score in students.items():
    # or event
    for student_name, (score1, score2, score3) in students.items():
        print(student_name, score1, score2, score3)
        #: Brian 94.0 89.0 92.0
      
  • Множественное сравнение в одном операторе — это вещь… И полезно в вашем случае.

     # For example:
    5 < 10 > 7 # will return True
    # So use this like:
    if score2 < score1 > score3:
        # score 1 is the highest
      

Ответ №2:

В вашем коде есть несколько ошибок :

  1. самый большой из них — это то, как вы пытаетесь получить каждую экзаменационную оценку. students это весь dict, поэтому для доступа к одной оценке вам нужно вызвать students[student_name][exam_number] . То, что говорит ваша ошибка, students[1] не существует.
  2. Вы неправильно выполняете цикл: ваш первый цикл проходит по имени учащихся ( students.keys() ), затем второй цикл проходит по всему dict, имени учащихся и вместе с их оценками. Это избыточно, и вы фактически не используете второй цикл.
  3. Индексы списка начинаются с, 0 поэтому в l=[6,7] вы можете вызвать l[0] (6) и l[1] (7); но l[2] находится за пределами списка.
  4. У вас должны быть круглые скобки вокруг ваших сравнений оценок.
  5. Это не ошибки, а предложения: У вас не должно быть print для каждого случая, есть способы просто получить индекс max. Вы также должны попытаться более четко называть свои переменные цикла, z это не очень явно, в то время как student or student_name является.

Вот первое исправление, которое остается близким к вашему исходному коду:

 students = {'Brian': (94,89,92), 'Rachel': (100,90,65), 'Jon': (67.5,95,100)}

for student,exams in students.items():  #students.iteritems() in python2
    if (exams[0] > exams[1]) amp; (exams[0] > exams[2]):
        print("For %s test 1 is the highest scored." % student)
    elif (exams[1] > exams[0]) amp; (exams[1] > exams[2]):
        print("For %s test 2 is the highest scored." % student)
    elif (exams[2] > exams[0]) amp; (exams[2] > exams[1]):
        print("For %s test 3 is the highest scored." % student)
  

Вот лучшая версия :

 for student,exams in students.items():  #students.iteritems() in python2
    best_exam = 1 exams.index(max(exams))
    print("For %s test %s is the highest scored." % (student,best_exam))