Python双键排序:仅反转第一个排序键的实现方法问询
嗨,我来帮你搞定这个排序问题!你现在遇到的情况是用sorted(s, key=lambda x: (x['date'], x['id']), reverse=True)时,reverse=True会把两个排序键都改成降序,导致同日期下ID大的排在前面,但你想要的是日期降序、同日期下ID升序的效果对吧?
问题回顾
- 当前代码输出:
ID DATE
1282 2019-12-19 12:09:28
1281 2019-12-19 12:09:28
1280 2019-12-19 12:09:28
1279 2019-12-19 12:09:27
1278 2019-12-19 12:09:27
1277 2019-12-19 12:09:27
1275 2019-12-19 12:09:27
- 期望输出:
1280 2019-12-19 12:09:28
1281 2019-12-19 12:09:28
1282 2019-12-19 12:09:28
1275 2019-12-19 12:09:27
1277 2019-12-19 12:09:27
1278 2019-12-19 12:09:27
1279 2019-12-19 12:09:27
两种可行解决方案
方案一:利用Python排序的稳定性,分两次排序
Python的sorted是稳定排序——意思是当两个元素的排序键相同时,它们的相对顺序会保持之前排序的结果。我们可以先按次要键(ID)升序排序,再按主键(日期)降序排序:
# 第一步:先按ID正序排序,确保同日期下ID的顺序是从小到大 s = sorted(s, key=lambda x: x['id']) # 第二步:按日期倒序排序,此时同日期的元素会保留第一步的ID正序 s = sorted(s, key=lambda x: x['date'], reverse=True)
这个方法的好处是不用额外处理日期格式,代码简单易懂,适合大多数场景。
方案二:修改排序键,将日期转换为可反向比较的数值
如果你的日期是标准的ISO格式字符串(比如2019-12-19 12:09:28),可以把它转换成时间戳,然后取负数,这样排序时负时间戳越小,对应的原日期越新;同时保持ID的正序,这样一次排序就能搞定:
from datetime import datetime # 将日期转为时间戳并取负,ID保持正序,直接升序排序即可实现需求 s = sorted(s, key=lambda x: (-datetime.strptime(x['date'], "%Y-%m-%d %H:%M:%S").timestamp(), x['id']))
这个方法只需要一次排序操作,效率稍高,适合数据量较大的场景。
效果验证
用上面任意一种方法处理后,就能得到你期望的输出:同日期下ID从小到大排列,日期从最新到最旧排列。
内容的提问来源于stack exchange,提问作者Chaban33

