Sort (排序)
Python 有两种排序:
- 原地排序(in-place)
- 改变原列表
- 返回值永远是 None
- 返回一个新列表
- 原对象不变(适用于 tuple、dict keys 等不可变序列)
data = [5, 1, 3]
data.sort()
# data = [1, 3, 5]
data = [5, 1, 3]
new_list = sorted(data)
# new_list = [1, 3, 5]
sorted(data, reverse=True)
等价于:
data.sort(reverse=True)
sort 和 sorted 均支持:
sorted(data, key=函数)
示例:按照字符串长度排序
words = ["apple", "a", "python", "hi"]
sorted(words, key=len)
示例:按照字典字段排序
data = [
{"name": "jack", "age": 20},
{"name": "lucy", "age": 18},
]
sorted(data, key=lambda x: x["age"])
按 age 升序,再按 name 升序
sorted(data, key=lambda x: (x["age"], x["name"]))
按 age 升序,但 name 逆序
sorted(data, key=lambda x: (x["age"], -ord(x["name"][0])))
更优雅方式:
sorted(data, key=lambda x: (x["age"], x["name"]), reverse=False)
但 reverse=True 会给所有字段倒序,不推荐用于多字段逆序。
class User:
def __init__(self, name, score):
self.name = name
self.score = score
users = [
User("a", 80),
User("b", 60),
]
sorted(users, key=lambda u: u.score)
from operator import itemgetter, attrgetter
对 dict 排序(比 lambda 快)
sorted(data, key=itemgetter("age"))
对对象排序
sorted(users, key=attrgetter("score"))
import locale
locale.setlocale(locale.LC_ALL, "zh_CN.UTF-8")
sorted(names, key=locale.strxfrm)
使用 functools.cmp_to_key:
from functools import cmp_to_key
def cmp(a, b):
if a["score"] > b["score"]:
return -1
if a["score"] < b["score"]:
return 1
return 0
sorted(data, key=cmp_to_key(cmp))
错误:
result = data.sort() # None!
正确:
data.sort()
# or
result = sorted(data)
data = {
"items": [
{"code": "600001", "score": 12},
{"code": "000005", "score": 20},
]
}
sorted_items = sorted(data["items"], key=lambda x: x["score"], reverse=True)
pairs = [(3, "a"), (1, "c"), (2, "b")]
sorted(pairs) # 默认按第1个,再按第2个字段
按数字排序(字符串转整数)
sorted(codes, key=lambda x: int(x))
只按前两位(行业分类常用)
sorted(codes, key=lambda x: x[:2])
sorted(data, key=lambda x: x["change"], reverse=True)
| 功能 | list.sort() | sorted() |
|---|---|---|
| 是否返回新对象 | ❌ 否 | ✅ 是 |
| 是否修改原对象 | ✅ 是 | ❌ 否 |
| 是否适用于任意 iterable | ❌ 否 | ✅ 是 |
| 推荐场景 | 长列表高性能排序 | 任何排序场景 |
| 任务 | 写法 |
|---|---|
| 升序排序 | sorted(data) |
| 降序排序 | sorted(data, reverse=True) |
| 按字段排序 | sorted(data, key=lambda x: x["k"]) |
| 多字段排序 | sorted(data, key=lambda x: (x["a"], x["b"])) |
| 排序对象 | sorted(users, key=lambda u: u.age) |
| 更高性能排序 | itemgetter/attrgetter |
| 自定义比较规则 | cmp_to_key |
| 原地排序 | data.sort() |