patternpythonMinor
HackerRank "Nested Lists" Code
Viewed 0 times
hackerranknestedcodelists
Problem
I completed the "Nested Lists" challenge on HackerRank, and would love any feedback on my code.
My program is fed text with the number of students in a classroom, the name of a student, and their grade. For example:
The code should return the student with the second lowest grade. Here's the output using the above input:
Here is my code:
My program is fed text with the number of students in a classroom, the name of a student, and their grade. For example:
4
Shadab
8
Varun
8.9
Sarvesh
9.5
Harsh
10The code should return the student with the second lowest grade. Here's the output using the above input:
VarunHere is my code:
def secondlow(students):
grades = []
for student in students:
grades.append(student[1])
sort_grades = sorted(grades)
seclow_grade = sort_grades[0]
for grade in sort_grades:
if grade != seclow_grade:
seclow_grade = grade
break
seclow_stud = []
for student in students:
if student[1] == seclow_grade:
seclow_stud.append(student[0])
for name in sorted(seclow_stud):
print(name)
students = []
for pupil in range(int(input())):
new_stud = [input(), float(input())]
students.append(new_stud)
secondlow(students)Solution
The code mostly follows usual coding style and reads good. I would just change
Now for the improvements:
Print vs return
Do not code too much behaviour into your functions. Let them compute their stuff and return the result so the caller can do whatever they want with it. It doesn't add much here, but it is a good habit to have.
Getting the value you are looking for
You do not need to store the only value you are looking for into a list. Especialy when using a for loop after that to extract the element out of the list:
Sorted
The
List-comprehensions
Python have these construct to easily build lists out of other iterables:
You can also use the same construct when building lists out of the input. Overall code would look like:
Dictionaries
I know that the challenge explicitly mentionned lists of lists, but Python have dictionaries that can map a value to another. You can use them as a replacement:
Or you can take advantage of the way you can retrieve items associated to others by switching the way you store your data:
Edit
After reading the challenge description again, I realised that there can be multiple students with the second lowest grade. And in fact, there might be cases where there are multiple student with the lowest grade. Making my point about having the second lowest grade as
Here I used the
Unfortunately, such requirements prevent you from using dictionaries the other way around.
secondlow to second_low and avoid using abreviations in variable names.Now for the improvements:
Print vs return
Do not code too much behaviour into your functions. Let them compute their stuff and return the result so the caller can do whatever they want with it. It doesn't add much here, but it is a good habit to have.
Getting the value you are looking for
seclow_stud = []
for student in students:
if student[1] == seclow_grade:
seclow_stud.append(student[0])You do not need to store the only value you are looking for into a list. Especialy when using a for loop after that to extract the element out of the list:
for student in students:
if student[1] == seclow_grade:
return student[0]Sorted
sort_grades = sorted(grades)
seclow_grade = sort_grades[0]
for grade in sort_grades:
if grade != seclow_grade:
seclow_grade = grade
breakThe
sorted builtin returns a list of values in increasing order. What is important to note here is that sort_grades is a list. So sort_grade[0] is the lowest grade and sort_grade[1] is the second lowest. No need to search for the value yourself, sorted already did the work for you.seclow_grade = sorted(grades)[1]List-comprehensions
grades = []
for student in students:
grades.append(student[1])Python have these construct to easily build lists out of other iterables:
grades = [student[1] for student in students]You can also use the same construct when building lists out of the input. Overall code would look like:
def secondlow(students):
grades = [student[1] for student in students]
seclow_grade = sorted(grades)[1]
for student in students:
if student[1] == seclow_grade:
return student[0]
students = [[input(), float(input())] for _ in range(int(input()))]
print(secondlow(students))Dictionaries
I know that the challenge explicitly mentionned lists of lists, but Python have dictionaries that can map a value to another. You can use them as a replacement:
def secondlow(students):
seclow_grade = sorted(students.values())[1]
for student in students.items():
if student[1] == seclow_grade:
return student[0]
students = {}
for _ in range(int(input())):
name = input()
grade = float(input())
students[name] = value
print(secondlow(students))Or you can take advantage of the way you can retrieve items associated to others by switching the way you store your data:
def secondlow(students):
second_low = sorted(students)[1]
return students[second_low]
students = {}
for _ in range(int(input())):
name = input()
grade = float(input())
students[value] = name # Note the switch here
print(secondlow(students))Edit
After reading the challenge description again, I realised that there can be multiple students with the second lowest grade. And in fact, there might be cases where there are multiple student with the lowest grade. Making my point about having the second lowest grade as
sorted(grades)[1] irrelevant… Unless you remove duplicates using a set:def second_low(students):
second_low_grade = sorted(set(students.values()))[1]
for student in students.items():
if student[1] == second_low_grade:
yield student[0]
students = {}
for _ in range(int(input())):
name = input()
grade = float(input())
students[name] = value
for second_lowest_student in second_low(students):
print(second_lowest_student)Here I used the
yield keyword to avoid building a list in second_low. What it does is allowing the function to return several results: one each time there is a match (if student[1] == second_low_grade). Here is the version using list of lists:def second_low(students):
grades = set(student[1] for student in students)
seclow_grade = sorted(grades)[1]
for student in students:
if student[1] == seclow_grade:
yield student[0]
students = [[input(), float(input())] for _ in range(int(input()))]
for second_lowest_student in second_low(students):
print(second_lowest_student)Unfortunately, such requirements prevent you from using dictionaries the other way around.
Code Snippets
seclow_stud = []
for student in students:
if student[1] == seclow_grade:
seclow_stud.append(student[0])for student in students:
if student[1] == seclow_grade:
return student[0]sort_grades = sorted(grades)
seclow_grade = sort_grades[0]
for grade in sort_grades:
if grade != seclow_grade:
seclow_grade = grade
breakseclow_grade = sorted(grades)[1]grades = []
for student in students:
grades.append(student[1])Context
StackExchange Code Review Q#133207, answer score: 5
Revisions (0)
No revisions yet.