本文要点
假设你在练习目录里准备了几条自建记录,每条记录是一个小字典,包含名称和数量两个字段
sorted默认按元素本身比较

本文目录
要保留原列表,就用sorted而不是原地排序
如果你手里有一份记录列表,想按某个字段排好序,同时又不能把原来的顺序弄丢,那么选择标准只有一条:用sorted,不用list.sort。
按Python官方文档的说明,sorted(iterable, *, key=None, reverse=False)从iterable中的项返回一个新的排序列表。也就是说,它不修改传入的可迭代对象,而是把排好序的结果作为新列表交给你。原列表仍然指向原来的对象,顺序不变。
这就是“保留原始列表”的实现方式:原列表留着,新列表单独接住。
本文只讨论sorted的key和reverse两个参数,用自建的记录列表做示例。不涉及list.sort的原地细节,也不涉及其他排序参数。所有数据都是练习用的自建示例,不是真实业务数据。动手前建议在练习目录里新建脚本,例如exercise/sort_demo.py,不要拿重要数据直接试。
自建记录:先写清楚输入长什么样
假设你在练习目录里准备了几条自建记录,每条记录是一个小字典,包含名称和数量两个字段。下面这段只是把数据写进脚本,不读取任何外部文件:
records = [
{"name": "绿茶", "qty": 3},
{"name": "红茶", "qty": 1},
{"name": "乌龙", "qty": 2},
]这份列表的原始顺序是绿茶、红茶、乌龙。后面无论怎么排序,我们都要能回头确认这个顺序还在。
为了核对,可以在排序前先把原始顺序复制一份留底:
original = [r["name"] for r in records]
print(original)运行后会打印出原始名称顺序。这一步是编辑建议的核对方法,不是必须步骤,但它能让你在排序后直接对比,确认原列表没被动过。
用key指定按哪个字段排
sorted默认按元素本身比较。对字典来说,直接比较字典没有意义,所以要用key告诉它:拿每个元素的哪一部分去比。
key接收一个函数,sorted会对每个元素调用它,用返回值作为排序依据。按数量字段排序可以写成:
by_qty = sorted(records, key=lambda r: r["qty"])
print(by_qty)这里lambda r: r["qty"]的作用是:对每条记录取出qty的值,sorted按这些数值从小到大排列。结果是数量1、2、3对应的记录依次排开。
关键点在于:by_qty是一个新列表,records还是原来那三条、原来那个顺序。你可以打印records再确认一次。
如果不想用lambda,也可以先定义一个普通函数,把函数名传给key,效果一样。选哪种只是写法差异,不影响返回新列表这一点。
用reverse改成从大到小
默认是从小到大。想反过来,把reverse设为True:
by_qty_desc = sorted(records, key=lambda r: r["qty"], reverse=True)
print(by_qty_desc)reverse=True表示降序排列,数量3的记录排在最前。reverse默认是False,也就是升序,所以不写它时就是从小到大。
这里要分清一件事:reverse改变的是排序方向,不是把升序结果倒过来再处理一遍。你只需要在调用时给出这个参数,sorted返回的新列表就是按降序排好的。
同样地,by_qty_desc是新列表,records不受影响。
排序后怎么核对原列表没被改动
光看代码容易漏掉“原列表到底动没动”这一步。可以用下面的方式核对(以下为编辑建议的检查方法,不是对某个程序的实测记录):
1. 排序前记录原始顺序,例如打印[ r["name"] for r in records ]。
2. 调用sorted,把结果赋给一个新变量。
3. 排序后再次打印records的名称顺序,和第一步对比。
4. 如果两次输出一致,说明原列表顺序未变;如果变了,检查是不是误用了原地排序方法。
这个核对的价值在于:sorted返回新列表是它的定义行为,但你在实际代码里可能把结果又赋回了原变量名,看起来像“原列表被改了”。例如写成records = sorted(records, ...),这时records这个名字指向了新列表,原来的列表对象虽然还在,但你已经拿不到它了。要保留原始列表,就别把新结果赋回同一个名字。
什么时候这种选择不适用
sorted返回新列表,代价是额外占用一份列表空间。如果你的列表非常大,又确实不需要保留原顺序,原地排序在内存上更省。但本文的范围是“排序时保留原始列表”,在这个前提下,sorted是直接对应的工具。
另外,key函数返回的值必须能相互比较。如果某条记录缺少qty字段,或者字段值类型不一致,排序时会报错。这不是sorted本身的问题,而是数据不齐导致的。遇到报错时,先检查每条记录是否都有key要取的那个字段。
本文只覆盖sorted的key和reverse,以及它返回新列表这一行为。list.sort的原地细节、稳定性、多级排序等内容不在本文范围内。所有示例均为自建练习数据,结论只针对这些示例的输入输出。
观看知识要点视频 18 秒
18秒无旁白要点导览,文字来自已审核正文;完整步骤、条件及参考资料见下方。
参考资料
以下原始资料提供本文依据;请结合日期、适用条件和产品说明查阅。
请结合原始资料的适用条件阅读。
返回表格与数据 →