3.1 KiB
3.1 KiB
#领域/Python
#复盘/5
一句话描述
[Python排序]
核心定义
围绕核心排序方法 sorted() 和 list.sort() 的实现,二者核心特性对比如下:
| 特性 | sorted(iterable) | list.sort() |
|---|---|---|
| 返回值 | 返回新的排序后列表,原数据保持不变 | 无返回值(None),原地修改原列表 |
| 适用对象 | 所有可迭代对象(列表、元组、字典等) | 仅列表(list)类型 |
| 内存占用 | 占用额外内存(生成新列表) | 无额外内存消耗(原地修改) |
| 常用场景 | 需保留原数据、非列表对象的排序需求 | 无需保留原数据、仅针对列表的排序场景 |
基础排序用法
# sorted():生成新列表
nums = [3, 1, 2]
new_nums = sorted(nums) # new_nums=[1,2,3], nums仍为[3,1,2]
# list.sort():原地修改
nums.sort() # nums变为[1,2,3],返回None
自定义排序规则
1. key 参数(lambda / 自定义函数)
- 单维度排序:
key=lambda 元素: 元素.属性 - 多维度排序:
key=lambda 元素: (属性1, 属性2)(优先按属性 1,相等则按属性 2)
# 优先x升序 → 其次y升序(你的核心需求)
sorted_list = sorted(msg_list, key=lambda m: (m.x, m.y))
# 反向:优先x降序 → 其次y降序
sorted_list_rev = sorted(msg_list, key=lambda m: (m.x, m.y), reverse=True)
# 更复杂场景:x升序,y降序(混合方向)
sorted_list_mix = sorted(msg_list, key=lambda m: (m.x, -m.y)) # -y实现y降序
重写类的比较方法(lt)
如果某个类的排序规则是 “长期固定” 的,可重写类的__lt__(小于)方法,Python 排序会自动基于<推导其他比较逻辑,无需指定key。
class Msg:
# x, y 属性
# 定义“小于”规则:先比x,再比y
def __lt__(self, other):
if not isinstance(other, Msg): # 避免类型错误,提升健壮性
return NotImplemented
if self.x != other.x:
return self.x < other.x
return self.y < other.y
# 直接排序,无需key
sorted_list = sorted(msg_list)
性能优化技巧
提前排序键
对于大规模数据(万级以上),提前提取排序键(避免重复计算)
# 先生成(键, 对象)元组列表,排序后提取对象(减少属性访问次数)
key_obj = [( (m.x, m.y), m ) for m in msg_list]
key_obj.sort()
sorted_list = [obj for (key, obj) in key_obj]
避免在key中使用复杂计算(如函数调用),优先预计算。
operator 替代 lambda
内置的 operator.attrgetter 更简洁、大规模数据下性能更好(底层是 C 实现)
# 等价于 lambda m: (m.x, m.y),但更快、更简洁
sorted_list = sorted(msg_list, key=attrgetter("x", "y"))
print(sorted_list) # [Msg(i=2, x=1, y=3), Msg(i=3, x=2, y=1), Msg(i=1, x=3, y=2)]
# 反向排序(x降→y升)
sorted_rev = sorted(msg_list, key=attrgetter("x", "y"), reverse=True)
注意事项
- 避免在
key中使用复杂函数调用,优先通过预计算简化排序键 - 大规模数据排序时,优先选择
list.sort()(原地修改)减少内存占用