订单该按付款顺序离开柜台,加急的除外。按一个字段排序不难,按两个字段就要用到元组了。哪个字段该排在前面,为什么?
排序本身不难,难的是记录有多个字段时该按什么排。Python 允许传入 key 函数,把每个元素转换成用于比较的值。这样既保留原记录,也让排序规则变得明确。 你还会用稳定排序叠加规则、用元组键混合升降序,并用 min/max 代替只为取一个值的排序。
sorted 返回新列表
sorted(items) 会创建新的排序列表,原列表不变。items.sort() 原地排序并返回 None。还需要保留原顺序时,用 sorted。
prices = [6.0, 4.5, 3.25]
print(sorted(prices))
print(prices)新的排序列表
用 key 排序记录
key 接收一个元素,返回 Python 应该比较的值。lambda 适合写很短的规则。这里的第二个字段 price 就是排序键。
orders = [("latte", 4.5), ("tea", 3.0), ("mocha", 5.0)]
for name, price in sorted(orders, key=lambda item: item[1]):
print(name, price)按价格排序元组
enumerate 与 zip
enumerate 同时给出索引和值。zip 把两个序列的元素配对。需要位置或并行数据时,它们能让循环保持清楚。
names = ["latte", "tea"]
prices = [4.5, 3.0]
for i, (name, price) in enumerate(zip(names, prices), 1):
print(i, name, price)索引与配对数据
稳定排序可以叠加规则
Python 的排序是稳定的:键相同的元素保持之前的相对顺序。先按次要规则排序,再按主要规则排序;第二次排序遇到相同主键时,会保留第一次的顺序。
orders = [
{"name": "tea", "price": 3.0},
{"name": "latte", "price": 4.5},
{"name": "mocha", "price": 4.5},
]
by_name = sorted(orders, key=lambda order: order["name"])
by_price = sorted(by_name, key=lambda order: order["price"], reverse=True)
for order in by_price:
print(order["name"], order["price"])先次键,后主键
元组键混合字段,不混合方向
元组键从左到右比较。(-price, name) 让价格降序、名称升序,因为负号只反转了价格这个字段。reverse=True 会把两个字段一起反转,通常不是想要的结果。
orders = [("latte", 4.5), ("tea", 3.0), ("mocha", 4.5)]
for name, price in sorted(orders, key=lambda item: (-item[1], item[0])):
print(name, price)用计算出的键只反转一个字段
只取一个记录时不必排序
只需要最便宜的一项时,min() 配 key 比完整排序更清楚,也更省。max() 同理。key 里的规则要和排序时使用的规则完全一致。
orders = [("latte", 4.5), ("tea", 3.0), ("mocha", 5.0)]
cheapest = min(orders, key=lambda item: item[1])
priciest = max(orders, key=lambda item: item[1])
print(cheapest)
print(priciest)取极值不需要完整顺序
本课要点
- sorted 返回新列表,sort 原地修改列表。
- key 决定按哪个值比较。
- reverse=True 从大到小排序。
- enumerate 加索引,zip 并行遍历两个序列。
- 稳定排序可以组合;元组键能只反转一个字段。
常见错误
- 把 sort() 的返回值赋回列表,结果得到 None。
- 调用 key 函数而不是把函数本身传进去。
- 以为 zip 会在较长序列结束后继续。
- 用了 reverse=True,却期待次要字段仍然升序。
按价格排序三个 (name, price) 元组,再打印每个名称和价格。
动手试试
改改变量、先预测输出,再运行代码。第一次点击“运行代码”时会下载 Python 运行时,可能需要几秒钟。
练习本课
12 道题,作答后立即看到解释。