How to find the second lowest lists into a nested list by their second value?

Question:

Here is given a nested list:

nl = [['Harsh', 20], ['Beria', 20], ['Varun', 19], ['Kakunami', 19], ['Vikas', 21]]

Now I have to find the second lowest lists into the nested list by their second value. And append the second lowest lists into another list.

So the output should be:

['Harsh', 20], ['Beria', 20]

I wrote the following code but it doesn’t work:

nl = [['Harsh', 20], ['Beria', 20], ['Varun', 19], ['Kakunami', 19], ['Vikas', 21]]

result=[]

temp=max(nl, key=lambda x: x[1])

largest, larger = temp[1], temp[1]
for num in nl:
    if num[1] < largest:
        largest, larger = num[1], largest
    elif num[1] < larger:
        larger = num[1]
        result.append(larger)
print(result)
Asked By: Abdullah Al Imran

||

Answers:

Here is a handy little function that incorporates heapq.nlargest:

Return a list with the n largest elements from the dataset


import heapq
num = heapq.nlargest(2, [key for item, key in nl])[-1]
print [item for item in nl if item[-1] == num] #[['Harsh', 20], ['Beria', 20]]
Answered By: A.J. Uppal

Your example can be simplified into this:

second_lowest = sorted(set(v[1] for v in nl))[1]
result = [v for v in nl if v[1] == second_lowest]
print(result) # [['Harsh', 20], ['Beria', 20]]

I use set of your values to find second, unique lowest value.
Than having this file, find elements in nl that match the found value.

Answered By: Marcin

Get the min of the total elements, filter using that valid then get min of remaining and keep elements equal to min of remaining:

from operator import itemgetter
# min of all elements
mn = min(nl, key=itemgetter(1))[1]

# remove elements equal to min
filtered = [x for x in nl if x[1] != mn]

# get min of remaining
mn_fil = min(filtered,key=itemgetter(1))[1]

# filter remaining
out = [x for x in filtered if x[1] == mn_fil]
print(out)

[['Harsh', 20], ['Beria', 20]]

Works for both your cases:

In [19]: nl = [['Prashant', 32], ['Pallavi', 36], ['Dheeraj', 39], ['Shivam', 40]]    
In [20]: from operator import itemgetter    
In [21]: mn = min(nl, key=itemgetter(1))[1]    
In [22]: filtered = [x for x in nl if x[1] != mn]    
In [23]: mn_fil = min(filtered,key=itemgetter(1))[1]    
In [24]: out = [x for x in filtered if x[1] == mn_fil]    
In [25]: out
Out[25]: [['Dheeraj', 36]]

Using a single for loop we remove all elements from the temp list if we find a lower element, if we find and equally lower one we append it:

mn = min(nl, key=itemgetter(1))[1]
temp = []
best = float("inf")
for ele in nl:
    if mn < ele[1] < best:
        best = ele[1]
        temp = []
        out.append(ele)
    elif ele[1] == best:
        temp.append(ele)
print(temp)
Answered By: Padraic Cunningham

I did it by finding the second lowest value using a set and then selecting elements from the list with the same value.

#ordering by value
nl.sort(key = lambda x: x[1])

values_set = set()
for value in nl:
    values_set.add(value[1])

values_list = list(values_set)
#ordering
values_list.sort()
#getting second lowest values
lowest_values = [lowest for lowest in nl if lowest[1] == values_list[1] ]
Answered By: D.A.Melo

You can try below code. It works fine.

lst=[['Harry',37.21],['Berry',37.21],['Tina',37.2],['Akriti',41],['Harsh',39]]
names=[]
lowest = lst[0].__getitem__(1)
second_lowest=0
for l in lst:
    if l[1] < lowest:
        second_lowest = lowest
        lowest = l[1]
    elif l[1]<=second_lowest:
        second_lowest=l[1]
for l in lst:
    if l[1]==second_lowest:
        names.append(l[0])


print(lowest)
print(second_lowest)
print(names)
Answered By: Ashlin Karkada
if __name__ == '__main__':
arr = []
for _ in range(int(input())):
    name = input()
    score = float(input())
    arr1 = [name, score]
    arr.append(arr1)
arr.sort(key=lambda x: x[1])
# print(arr)
# print(min(arr,key=lambda x:x[1]))
arr.remove(min(arr,key=lambda x:x[1]))
# print(arr)
minimum = min(arr,key=lambda x:x[1])
# print(minimum[1])
a=[]
minimum = minimum[1]
for i  in arr:
    if(i[1] == minimum):
        a.append(i[0])
a.sort()
for i in a:
    print(i)
Answered By: akshay kumar

I have come across similar kind of problem and after referring this page I got some ideas and able to solve it.

nl = [['Harsh', 20], ['Beria', 20], ['Varun', 19], ['Kakunami', 19], ['Vikas', 21]]

second = max(nl, key= lambda x: x[1])[1]
first = min(nl, key= lambda x: x[1])[1]
    
for i in range(len(nl)):
    if nl[i][1] <= second and nl[i][1] != first:
        second = nl[i][1]
    
for i in range(len(nl)):
    if second == nl[i][1]:
        print(nl[i], end=", ")
Answered By: Sudhakar
if __name__ == '__main__':

    n = []
    s = []
    for _ in range(int(input())):
        name = input()
        n.append(name)
        score = float(input())
        s.append(score)
        
data = [[x,y] for x,y in zip(n,s)]

min_marks = min([x[1] for x in data])

filtered_data = [d for d in data if d[1] != min_marks]

sec_min = min([x[1] for x in filtered_data])

students_with_sec_min_marks = sorted([d[0] for d in filtered_data if d[1] == sec_min])

for s in students_with_sec_min_marks:
    print(s)
Answered By: Irfan_Ahmed
if __name__ == '__main__':
    lst = []
    names = []
    for _ in range(int(input())):
        name = input()
        score = float(input())
        lst.append([name, score])
     
    lowest = max(lst, key=lambda x: x[1])[1]
    second_lowest=0
    for l in lst:
        if l[1] < lowest:
            second_lowest = lowest
            lowest = l[1]
        elif l[1] < second_lowest and l[1] != lowest:
            second_lowest = l[1]
    for l in lst:
        if l[1] == second_lowest:
            names.append(l[0])  
    
    names.sort()
    for nm in names:
        print(nm)

I used the below code and it worked good:

records = []

if __name__ == '__main__':
    for i in range(int(input())):
        name = input()
        score = float(input())
        records.append([name,score])
        records.sort(key=lambda x:x[1])
    minimum = min(records,key=lambda x:x[1])
    minimum = minimum[1]
    args = records.copy()
    
    for i in args:
        if(i[1] == minimum):
            records.remove(i)
        else:
            continue
    
    minimum = min(records,key=lambda x:x[1])
    minimum = minimum[1]
    a=[]
    for i  in records:
        if(i[1] == minimum):
            a.append(i[0])

    a.sort()
    for i in a:
        print(i)

This way, you will also be able to remove multiple same lowest scores if they exist. Running it without copy() and working on the original list causes the loop to miss the several same lowest scores.

Answered By: Bilal Sedef
students=[]
if __name__ == '__main__':
    for _ in range(int(input())):
        name = input()
        score = float(input())
        students.append([name,score])
    
            
students.sort(key=lambda x:x[1]  )  
students.remove(min(students,key=lambda x:x[1] ))
names=[]
score=students[0][1]
for student in students:
    if student[1]==score:
        names.append(student[0])
names.sort()
for each in names:
    print(each)
Answered By: KURRA PRAVEEN