S.Keizer S.Keizer - 3 months ago 32
Python Question

Trying to sort a list of tuples in python first by date then by greatest number

I have a list of tuples and I am trying to sort by date and then by the greatest number. So basically when you have two dates that are the same it will then put the tuple with the greatest number first. See example below.

My list of tuples

dataLst = [["Mike", 50, "08/10/2016"], ["Bob", 100, "08/10/2016"], ["Dave", 500, "08/01/2016"], ["Paul", -50, "08/20/2016"], ["Sam", 250, "08/30/2016"]]


I then sort the list by the dates in the tuples.

sDataLst = sorted(dataLst, key=operator.itemgetter(2))


I then sort the sorted list by the numbers in reverse order.

sorted(sDataLst,key=operator.itemgetter(1), reverse=True)


When I print the sorted list I get the following.

print sDataLst

[['Dave', 500, '08/01/2016'], ['Mike', 50, '08/10/2016'], ['Bob', 100, '08/10/2016'], ['Paul', -50, '08/20/2016'], ['Sam', 250, '08/30/2016']]


If you look at the second and third item in the list which have the same date they should be reversed because the number in the third item is greater then the one in the second item. What I am looking for as a result is the following.

[['Dave', 500, '08/01/2016'], ['Bob', 100, '08/10/2016'], ['Mike', 50, '08/10/2016'], ['Paul', -50, '08/20/2016'], ['Sam', 250, '08/30/2016']]


Any help on this would be greatly appreciated.

Thanks

Answer

You need to reverse the order of the sorts - the "tie-breakers" are done before the "main" sort which works because Python's sort is stable, so they retain the order of the tiebreaker when sorted into the main order, eg:

from datetime import datetime
from operator import itemgetter

dataLst = [["Mike", 50, "08/10/2016"], ["Bob", 100, "08/10/2016"], ["Dave", 500, "08/01/2016"], ["Paul", -50, "08/20/2016"], ["Sam", 250, "08/30/2016"]]
# Sort the tie breaker first
dataLst.sort(key=itemgetter(1), reverse=True)
# Sort on the main key - here we'll use `strptime` to sort as a proper date
dataLst.sort(key=lambda L: datetime.strptime(L[2], '%m/%d/%Y'))

This gives:

[['Dave', 500, '08/01/2016'],
 ['Bob', 100, '08/10/2016'],
 ['Mike', 50, '08/10/2016'], # Bob and Mike properly ordered...
 ['Paul', -50, '08/20/2016'],
 ['Sam', 250, '08/30/2016']]