With a Python list of dictionaries which always contains start
and end
dates, how would you sort the list based on the "combined" start
and end
dates?
What would be the simplest (most Pythonic) way to obtain the end result with the following criteria - from top to bottom:
end_date
(descending) first and then by start_date
(descending).end_date
, then the latest start_date
comes first i.e.: then order by the start_date
for those items.start_date
and the end_date
be the same, then the ordering of those items is not a concern and can be ignored or remain as is.import datetime
blah = [
{"id": 1, "start_date": datetime.date(2021, 5, 1), "end_date": None},
{"id": 2, "start_date": datetime.date(2013, 2, 1), "end_date": None},
{"id": 3, "start_date": datetime.date(2017, 1, 1), "end_date": datetime.date(2018, 1, 1)},
{"id": 4, "start_date": datetime.date(2016, 5, 1), "end_date": datetime.date(2019, 6, 1)},
{"id": 5, "start_date": datetime.date(2012, 1, 1), "end_date": datetime.date(2015, 1, 1)},
{"id": 6, "start_date": datetime.date(2008, 1, 1), "end_date": datetime.date(2011, 1, 1)},
{"id": 7, "start_date": datetime.date(2006, 1, 1), "end_date": datetime.date(2008, 1, 1)},
{"id": 8, "start_date": datetime.date(2005, 1, 15), "end_date": datetime.date(2010, 1, 15)},
{"id": 9, "start_date": datetime.date(2002, 1, 15), "end_date": datetime.date(2002, 1, 15)},
{"id": 10, "start_date": datetime.date(2002, 1, 1), "end_date": datetime.date(2006, 1, 1)},
{"id": 11, "start_date": datetime.date(2002, 1, 1), "end_date": datetime.date(2006, 1, 1)},
{"id": 12, "start_date": datetime.date(2001, 2, 1), "end_date": datetime.date(2003, 1, 1)},
{"id": 13, "start_date": datetime.date(2001, 1, 15), "end_date": datetime.date(2003, 1, 15)},
{"id": 14, "start_date": datetime.date(1998, 1, 1), "end_date": datetime.date(2001, 1, 1)},
{"id": 15, "start_date": datetime.date(1997, 1, 15), "end_date": datetime.date(1997, 1, 15)}
]
# Do something here...and return `result`.
result = [
{"id": 1, "start_date": datetime.date(2021, 5, 1), "end_date": None},
{"id": 2, "start_date": datetime.date(2013, 2, 1), "end_date": None},
{"id": 4, "start_date": datetime.date(2016, 5, 1), "end_date": datetime.date(2019, 6, 1)},
{"id": 3, "start_date": datetime.date(2017, 1, 1), "end_date": datetime.date(2018, 1, 1)},
{"id": 5, "start_date": datetime.date(2012, 1, 1), "end_date": datetime.date(2015, 1, 1)},
{"id": 6, "start_date": datetime.date(2008, 1, 1), "end_date": datetime.date(2011, 1, 1)},
{"id": 8, "start_date": datetime.date(2005, 1, 15), "end_date": datetime.date(2010, 1, 15)},
{"id": 7, "start_date": datetime.date(2006, 1, 1), "end_date": datetime.date(2008, 1, 1)},
{"id": 11, "start_date": datetime.date(2002, 1, 1), "end_date": datetime.date(2006, 1, 1)},
{"id": 10, "start_date": datetime.date(2002, 1, 1), "end_date": datetime.date(2006, 1, 1)},
{"id": 9, "start_date": datetime.date(2002, 1, 15), "end_date": datetime.date(2002, 1, 15)},
{"id": 12, "start_date": datetime.date(2001, 2, 1), "end_date": datetime.date(2003, 1, 1)},
{"id": 13, "start_date": datetime.date(2001, 1, 15), "end_date": datetime.date(2003, 1, 15)},
{"id": 14, "start_date": datetime.date(1998, 1, 1), "end_date": datetime.date(2001, 1, 1)},
{"id": 15, "start_date": datetime.date(1997, 1, 15), "end_date": datetime.date(1997, 1, 15)}
]
You can simply sort your data with the appropriate key to satisfy points 1-3; point 4 is automatically satisfied since the sort in Python is guaranteed to be stable:
result = sorted(blah,
reverse = True,
key=lambda d:(
d["end_date"] if d["end_date"] is not None else datetime.date(2999,12,31),
d["start_date"])
)