0

I wrote this for my beginner class and I don't know how to get the NAME of the SECOND STUDENT with the 2nd highest score. After testing it, I believe the code works for the first student.

I think what I need is to store the highest score in to variable high_score and then the next highest in to second_score and then compare the third score to both the highest and second score. But I am confused on how to get the name of the second highest scoring student.

num_students = int(input("enter number of students: "))
high_score = 0
high_name = ""
second_name = ""
second_score = 0
for i in range(1,num_students + 1):
 if num_students < 2:
 break
 if num_students >= 2:
 name = input("enter student name: ")
 score = int(input("enter student score: "))
 if score > second_score:
 if score > high_score:
 second_score = high_score
 high_score = score
 high_name = name
 elif score < high_score:
 second_score = score
 second_name = name
print()
print("Top Two Students")
print()
print(high_name,"'s score is", high_score)
print(second_name,"'s score is", second_score)
asked Oct 17, 2021 at 15:45
2
  • 1
    You can use a list of two tuples for storing student information. You can sort the list based on scores DESC and then get the first two elements. Commented Oct 17, 2021 at 15:54
  • 1
    A few things... After your "if num_students < 2: break" you don't need the next "if num_students >= 2:" . Also, when you determine that the current score is bumping the high score and you update the second_score = high_score, you should add a line to update the second_name at the same time. Other than that, without running your code, it looks like it should work. Also, your last "elif score < high_score:" could just be an "else:" Commented Oct 17, 2021 at 16:07

3 Answers 3

2

In addition to Gary02127's solution, I'd like to point out a few other improvements:

  • You should move if num_students < 2 outside of your loop. It would be enough to check the condition once after the user inputted the number of students.

  • You could also write for i in range(num_students). It doesn't matter if the range starts with 0 or 1 since you are not using i.

  • Also, if you are not using a variable, you could use _ (throwaway variable) instead. See more about for _ in range(num_students) here: What is the purpose of the single underscore "_" variable in Python?.


Instead of:

if score > second_score:
 if score > high_score:
 # ...
 else: 
 # ...

You could also write:

if high_score < score:
 # ...
elif second_score < score:
 # ...

Here is a verbose solution considering suggested improvements:

num_students = int(input("Enter number of students: "))
if num_students < 2:
 exit()
highest_name = None
highest_grade = 0
second_highest_name = None
second_highest_grade = 0
for _ in range(num_students):
 name = input("Enter student's name: ")
 grade = int(input("Enter student's score: "))
 if highest_grade < grade:
 second_highest_name = highest_name
 second_highest_grade = highest_grade
 
 highest_name = name
 highest_grade = grade
 elif second_highest_grade < grade:
 second_highest_name = name
 second_highest_grade = grade
print(highest_name, highest_grade) # highest grade
print(second_highest_name, second_highest_grade) # second highest grade

You could also use a list and sorted() (built-in function):

from operator import itemgetter
num_students = int(input("Enter number of students: "))
if num_students < 2:
 exit()
 
grades = []
for _ in range(num_students):
 name = input("Enter student's name: ")
 grade = int(input("Enter student's score: "))
 grades.append((name, grade))
 
grades = sorted(grades, key=itemgetter(1), reverse=True)
print(grades[0]) # highest grade 
print(grades[1]) # second highest grade

You could also use a specialized list such as SortedList (requires external package):

from sortedcontainers import SortedList
num_students = int(input("Enter number of students: "))
if num_students < 2:
 exit()
 
grades = SortedList(key=lambda record: -record[1])
for _ in range(num_students):
 name = input("Enter student's name: ")
 grade = int(input("Enter student's score: "))
 grades.add((name, grade))
print(grades[0]) # highest grade 
print(grades[1]) # second highest grade

Notes:

  • Difference between sorted() and str.sort(). sorted() creates a new sorted list whereas str.sort() modifies the current list.
  • itemgetter(1) is equals to lambda record: record[1].
  • You can install SortedList with: pip install sortedcontainers.
answered Oct 17, 2021 at 19:09
Sign up to request clarification or add additional context in comments.

Comments

1

Here's a solution based on my previous comments to your original post.

num_students = int(input("enter number of students: "))
high_score = 0
high_name = ""
second_name = ""
second_score = 0
for i in range(1,num_students + 1):
 if num_students < 2:
 break
 # if num_students >= 2: # don't need this "if" after previous "break"
 name = input("enter student name: ")
 score = int(input("enter student score: "))
 if score > second_score:
 if score > high_score:
 second_score = high_score
 second_name = high_name # NEW
 high_score = score
 high_name = name
 else: # simplified to just a plain "else:"
 second_score = score
 second_name = name
print()
print("Top Two Students")
print()
print(high_name,"'s score is", high_score)
print(second_name,"'s score is", second_score)

Notice that simplifying that last "elif ...:" to a simple "else:" also solves a simple bug where entering the current high score again can be ignored and not captured. If you were to run your code as is and use input values "100 80 100", you would find the 2nd high score set to 80 instead of 100.

Nimantha
6,5476 gold badges32 silver badges78 bronze badges
answered Oct 17, 2021 at 16:17

3 Comments

If possible, could you explain why an "elif" instead of an "else" at the end would cause that to happen?
@optik404 - sure... when (new) score == high-score, you fail the "if" test and you fail the "else if" test, because the "else if" is checking for score < high_score. But in that instance, score is equal to high_score, so the situation doesn't get handled. You "fall off" the if/else-if tree without handling that condition. By changing the elif to just an else, you catch the state when score is equal to high_score, so it gets processed instead of missed. You could have changed the elif score < high_score: to elif score <= high_score, but that's logically the same as the simple "else"
@optik404 if/elif trees are great in general, but it's always nice to end with an "else" to make sure that every situation gets handled. One last little blurb... if a < b: ... elif a > b: ... will not handle the case where a == b. And that was one of your bugs.
0

You can simply store the details in a list. And use list.sort() to sort the values according to the score.

Here is the working code:

num_students = int(input("Enter number of students: "))
scores = []
if num_students < 2:
 print('Number of students less than 2')
 exit()
for i in range(num_students):
 name = input("Enter student's name: ")
 score = int(input("Enter student's score: "))
 scores.append([name, score])
scores.sort(key=lambda details: details[1], reverse=True)
print("Top Two Students")
print()
print(f"{scores[0][0]}'s score is {scores[0][1]}")
print(f"{scores[1][0]}'s score is {scores[1][1]}")
answered Oct 17, 2021 at 15:57

1 Comment

Unfortunately we haven't learned lists yet.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.