-1

Suppose there is a list like [name,score]

record = [['Harry',37.21],['Berry',37.21],['Tina',37.2],['Akriti',41],['Harsh',39]]

I want to print the name of record which has second lowest score. If two records have same lowest score I need to sort them based on their names and then print. I know we can use

record.sort(key..)

to get values sorted according to score. But how to check for second lowest score and then check for name.

4
  • the second lowest would be record[1] if the list is sorted from low to high based on its score Commented May 3, 2015 at 1:19
  • But will I sort the second lowest record again based on name ? Commented May 3, 2015 at 1:20
  • I dont understand what you are asking... Commented May 3, 2015 at 1:21
  • @b4hand thats not really a duplicate ... close but there is no secondary sort in the case of ties Commented May 3, 2015 at 1:24

4 Answers 4

6
second_lowest = sorted(my_list,key=lambda x:x[::-1])[1]

not sure what you mean about ties and whatnot ... but this should sort first by score and sort ties by alphabetical name, by reversing the items we are sorting records of [score,name]

this basically just abuses the fact that tuples/lists naturally sort on progressive keys when the first key ties

sorted([[1,2,3],[1,2,4],[3,2,1],[1,1,2]])
Sign up to request clarification or add additional context in comments.

9 Comments

I disagree that that's an abuse :-)
I don't think that's what the OP wanted. he wanted a sorting by grade, reversed, and then by alphabetical order: "If two records have same lowest score I need to sort them based on their names and then print"
this will sort alphabetically on the name in the case of any tie .... regardless of where the tie occures ... Im not sure how that doesnt answer the question
ok fixed... the problem was that reversed returns a generator instead of a list
Yes, this one is much better. I will vote it up in this situation, but what if we want different order on name and score?
|
4

Like others have said, you can easily get a list sorted on value and name by reversing the sublists.

>>> sorted_data = sorted(record, key=lambda x: x[::-1])
>>> sorted_data
[['Tina', 37.2], ['Berry', 37.21], ['Harry', 37.21], ['Harsh', 39], ['Akriti', 41]]

But it seems that you want all second lowest values. Obviously you cannot just index sorted_data[1] then. I would suggest an approach like this,

>>> from itertools import groupby
>>> [list(sublist) for _, sublist in groupby(sorted_data, lambda x: x[1])][1]
[['Berry', 37.21], ['Harry', 37.21]]

This groups your sorted data on the value to easily allow you to access all [name, value] pairs having the same second smallest value.

1 Comment

I read the question again and it seems that this is indeed what he was trying to ask.
2
second = sorted(record, key=lambda(a,b):(b,a))[1]

Comments

0

If you want to have a more flexible way, like using different order for name and score, you can use cmp. Try this:

cfunc = lambda x,y: cmp(x[0],y[0]) if x[1] == y[1] else cmp(x[1],y[1])
record.sort(cmp=cfunc)
record[1]

Or:

cfunc = lambda x,y: -cmp(x[0],y[0]) if x[1] == y[1] else cmp(x[1],y[1])

Depends on whether you want to sort the name ascending or descending.

The general idea here is you have to define the order explicitly. In this case it's defined by the cfunc. See the document for detail: https://docs.python.org/2/library/functions.html#cmp

4 Comments

while this does work to a novice python programmer this is not very clear in what its doing ...additionally I believe python recommends using key= instead of cmp in sorts (as it is faster) (that said the -1 isnt from me and I will offset it with a +1 since this is technically a correct answer)
I agree this is probably not very pythonic but it's kind of more general than your answer and I would definitely want to see a more pythonic solution than both our answer. Thanks for the offset as well.
you should point out the case where this might method may be more appropriate (just copy your comment on my answer to this answer)
Why not lambda x,y: cmp(x[1],y[1]) or cmp(x[0],y[0])?

Your Answer

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.