'python: how to sort a complex list on two different keys
I have a weird list built in the following way:
[[name_d, 5], [name_e, 10], [name_a, 5]]
and I want to sort it first by the number (desc) and then, if the number is the same, by the name (asc). So the result I would like to have is:
[[name_e, 10], [name_a, 5], [name_d, 5]]
I tried to think to a lambda function that I can use in the sort method, but I'm not sure I can do it.
Solution 1:[1]
You may sort the list twice to get the result, just reverse the order:
import operator
l = [[name_d, 5], [name_e, 10], [name_a, 5]]
l.sort(operator.itemgetter(1))
l.sort(operator.itemgetter(0), reverse=True)
Then you will get the sorted list as expected.
Solution 2:[2]
Here's something I whipped up (to solve the same type of problem). I've only checked it with my latest versions of installed Python (OS X). The import parts below are the (clunkily-named) sort keys: sortKeyWithTwoListOrders and sortKeyWith2ndThen1stListValue
#Tested under Python 2.7.1 & Python 3.2.3:
import random # Just to shuffle for demo purposes
# Our two lists to sort
firstCol=['abc','ghi','jkl','mno','bcd','hjk']
secondCol=[5,4,2,1]
# Build 2 dimensional list [[firstCol,secondCol]...]
myList = []
for firstInd in range(0, len(firstCol)):
for secondInd in range(0, len(secondCol)):
myList = myList + [[firstCol[firstInd],secondCol[secondInd]]]
random.shuffle(myList)
print ("myList (shuffled):")
for i in range(0,len(myList)):
print (myList[i])
def sortKeyWithTwoListOrders(item):
return secondCol.index(item[1]), firstCol.index(item[0])
myList.sort(key=sortKeyWithTwoListOrders)
print ("myList (sorted according to strict list order, second column then first column):")
for i in range(0,len(myList)):
print (myList[i])
random.shuffle(myList)
print ("myList (shuffled again):")
for i in range(0,len(myList)):
print (myList[i])
def sortKeyWith2ndThen1stListValue(item):
return item[1], item[0]
myList.sort(key=sortKeyWith2ndThen1stListValue)
print ("myList (sorted according to *values*, second column then first column):")
for i in range(0,len(myList)):
print (myList[i])
myList (shuffled):
['ghi', 5]
['abc', 2]
['abc', 1]
['abc', 4]
['hjk', 5]
['bcd', 4]
['jkl', 5]
['jkl', 2]
['bcd', 1]
['ghi', 1]
['mno', 5]
['ghi', 2]
['hjk', 2]
['jkl', 4]
['mno', 4]
['bcd', 2]
['bcd', 5]
['ghi', 4]
['hjk', 4]
['mno', 2]
['abc', 5]
['mno', 1]
['hjk', 1]
['jkl', 1]
myList (sorted according to strict list order, second column then first column):
['abc', 5]
['ghi', 5]
['jkl', 5]
['mno', 5]
['bcd', 5]
['hjk', 5]
['abc', 4]
['ghi', 4]
['jkl', 4]
['mno', 4]
['bcd', 4]
['hjk', 4]
['abc', 2]
['ghi', 2]
['jkl', 2]
['mno', 2]
['bcd', 2]
['hjk', 2]
['abc', 1]
['ghi', 1]
['jkl', 1]
['mno', 1]
['bcd', 1]
['hjk', 1]
myList (shuffled again):
['hjk', 4]
['ghi', 1]
['abc', 5]
['bcd', 5]
['ghi', 4]
['mno', 1]
['jkl', 1]
['abc', 1]
['hjk', 1]
['jkl', 2]
['hjk', 5]
['mno', 2]
['jkl', 4]
['ghi', 5]
['bcd', 1]
['bcd', 2]
['jkl', 5]
['abc', 2]
['hjk', 2]
['abc', 4]
['mno', 4]
['mno', 5]
['bcd', 4]
['ghi', 2]
myList (sorted according to *values*, second column then first column):
['abc', 1]
['bcd', 1]
['ghi', 1]
['hjk', 1]
['jkl', 1]
['mno', 1]
['abc', 2]
['bcd', 2]
['ghi', 2]
['hjk', 2]
['jkl', 2]
['mno', 2]
['abc', 4]
['bcd', 4]
['ghi', 4]
['hjk', 4]
['jkl', 4]
['mno', 4]
['abc', 5]
['bcd', 5]
['ghi', 5]
['hjk', 5]
['jkl', 5]
['mno', 5]
Solution 3:[3]
Let's give your list a name - "arr"
arr.sort(key=lambda x:(x[0],-x[1]),reverse=True)
output - [[name_e,10],[name_d,5],[name_a,5]]
Solution 4:[4]
It doesn't need to be a lambda function you pass into the sort method, you can actually provide a real function since they are first-class objects in python.
L.sort(my_comparison_function)
Should work just fine
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Maelstrom |
| Solution 2 | hEADcRASH |
| Solution 3 | |
| Solution 4 | Daniel DiPaolo |
