Reputation: 333
Given the names and grades for each student in a Physics class of N students, store them in a nested list and print the name(s) of any student(s) having the second lowest grade.
Note: If there are multiple students with the same grade, order their names alphabetically and print each name on a new line.
Input
students = [['Harry', 37.21], ['Berry', 37.21], ['Tina', 37.2], ['Akriti', 41], ['Harsh', 39]]
Below is my code for the above question :-
marks = sorted([student[i][1] for i in range(len(student))], reverse = True)
for num in range(1,len(marks)):
if marks[num] < marks[0]:
if marks[num+1] < marks[num]:
temp = marks[num+1]
break
else:
continue
second_top = [student[i] for i in range(len(student)) if student[i][1] == temp]
topper = sorted([k for k,l in second_top])
for i in range(len(topper)):
print(topper[i])
Ouptut
Berry
Harry
Is there a way to improve this code. I'm a new to Python started practising on Hacker rank
Upvotes: 1
Views: 2143
Reputation: 1041
Try this, which accounts for ex-aequos too:
students = [['Harry', 37.21], ['Berry', 37.21], ['Tina', 37.2], ['Joe', 37.2], ['Akriti', 41], ['Harsh', 39]]
scores = sorted(set([s[1] for s in students]))
students_by_score = {score: [student for student in students if student[1] == score] for score in scores}
second_bests = students_by_score[scores[1]] # or whichever rank you want
print(second_bests)
Result:
[['Berry', 37.21], ['Harry', 37.21]]
Upvotes: 3
Reputation: 1
A newbie way to do it: Clears all the tests!!!
listb=[] (creating an empty list)
n=int(input()) (number of items in list)
for i in range(n): (loop initiated for creating a list A with names)
lista=[]
name = input()
lista.append(name)
for j in range (1): (loop for entering the score in list a, and making list b)
score = float(input())
lista.append(score)
listb.append(lista)
listc=sorted(listb, key=lambda i: i[1]) (sort the list)
minx=min(listc, key=lambda i: i[1]) (taking minimum value)
second_minimum_score = max(listc, key=lambda i: i[1]>minx[1]) (extracting second minimum value)
my_value=second_minimum_score[1]
chaapo=[] (this list will contain our answer)
for i in range(len(listc)):
if listc[i][1]==my_value:
chaapo.append(listc[i][0])
y=sorted(chaapo)
for i in range (len(y)): (loop for printing, if there are multiple names)
print(y[i])
Upvotes: 0
Reputation: 17322
you could use a list comprehension with itertools.groupby and itertools.islice:
from itertools import groupby, islice
s = [i[0] for e in islice((list(g) for k, g in groupby(sorted(students), key=lambda x: x[1])), 1, 2) for i in e]
print(*s, sep='\n')
output:
Berry
Harry
another approach will be to store your data in a dict where the key will be the grade and the values will be a list with all the students that have the grade specified by the key:
from collections import defaultdict
grade_student = defaultdict(list)
for student, grade in students:
grade_student[grade].append(student)
# second lowest grade
second_grade = sorted(grade_student.keys())[1]
# order the names alphabetically and print each name on a new line
print(*sorted(grade_student[second_grade]), sep='\n')
output:
Berry
Harry
Upvotes: 2
Reputation: 8180
First of all, I would sort the grades y ascending order:
>>> students = [['Harry', 37.21], ['Berry', 37.21], ['Tina', 37.2], ['Akriti', 41], ['Harsh', 39]]
>>> grades = sorted(set(g for _, g in students))
>>> grades
[37.2, 37.21, 39, 41]
The line set(g for _, g in students)
extract the grades and remove the duplicates (set
).
Then take the second element of the list, which is the second lowest grade:
>>> second_lowest_grade = grades[1]
>>> second_lowest_grade
37.21
And then loop on ordered names (alpabetically) for students having the second lowest grade:
>>> for name in sorted(n for n, g in students if g == second_lowest_grade):
... print(name)
...
Berry
Harry
Upvotes: 4