0
list = [["hasan",6,"bad","chennai"], ["vishnu",7,"good","chennai"], ["tabraiz",8,"good","bangalore"], ["shaik",5,"excellent","chennai"], ["mani",6,"avarage","kerala"], ["cilvin",9,"excellent","chennai"]]

given priority as

{'excellent':4, 'good':3, 'average':2, 'bad':1}    

list.sort(key=lambda x: (x[3], -x[2], -x[1]))
list.sort(key=lambda x: (x[2], x[0], -x[1]))
list.sort(key=lambda x: (x[2], -x[3], x[0]))

These all are working.

but it says

TypeError: bad operand type for unary -: 'str'

when trying to place negative sign in the first position.

ie

list.sort(key=lambda x: (-x[3], x[2], x[1]))

why????

7
  • 1
    Unary minus operator works properly, in sorting, with numeric data only. Commented Jan 17, 2014 at 9:28
  • Well, is the first element of each sub-list a string? Because that would cause exactly this problem. Commented Jan 17, 2014 at 9:29
  • yes, that is why this problem. how to fix it??? Commented Jan 17, 2014 at 9:39
  • 1
    These all are working. I do doubt that. Please double check it. To be specific, only list.sort(key=lambda x: (x[2], x[0], -x[1])) shall work. Also don't override built-in identifiers like list. Commented Jan 17, 2014 at 9:39
  • What are you trying to achieve? Do you want to order first by x[3] in decreasing order, then by x[2] in increasing order and then by x[1] in increasing order? Commented Jan 17, 2014 at 9:41

1 Answer 1

1

The problem with your method is that x[3] is a string, so it does not make sense to do -x[3].

I am not sure there isn't a simpler solution, but you can use cmp_to_key, and define your own reversed key function:

from functools import cmp_to_key

l = [['hasan', 6, 'bad', 'chennai'],
     ['vishnu', 7, 'good', 'chennai'],
     ['tabraiz', 8, 'good', 'bangalore'],
     ['shaik', 5, 'excellent', 'chennai'],
     ['mani', 6, 'avarage', 'kerala'],
     ['cilvin', 9, 'excellent', 'chennai']]

rev_key = cmp_to_key(lambda x,y: 1 if x<y else -1 if x>y else 0)
l.sort(key=lambda x: (rev_key(x[3]), x[2], x[1]))
print(l)

Result:

[['mani', 6, 'avarage', 'kerala'],
 ['hasan', 6, 'bad', 'chennai'],
 ['shaik', 5, 'excellent', 'chennai'],
 ['cilvin', 9, 'excellent', 'chennai'],
 ['vishnu', 7, 'good', 'chennai'],
 ['tabraiz', 8, 'good', 'bangalore']]

Note that if you're using Python 2, you can just write:

rev_key = cmp_to_key(lambda x,y: cmp(y,x))

If you didn't want to sort according to several keys, the right way to go would be to use the reverse argument:

>>> sorted(l, key=lambda x: x[3], reverse=True)
[['mani', 6, 'avarage', 'kerala'],
 ['hasan', 6, 'bad', 'chennai'],
 ['vishnu', 7, 'good', 'chennai'],
 ['shaik', 5, 'excellent', 'chennai'],
 ['cilvin', 9, 'excellent', 'chennai'],
 ['tabraiz', 8, 'good', 'bangalore']]
Sign up to request clarification or add additional context in comments.

Comments

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.