Python排序函数 sorted
中等0用sorted轻松搞定排序——从扑克牌到成绩排名
当你手里有一堆乱七八糟的数字、名字或者成绩,想把它们按顺序排好,就像整理扑克牌一样,Python的sorted函数就是你的好帮手。它能把任何可迭代对象(比如列表、元组、字符串、字典等)按从小到大或从大到小的顺序排好,并返回一个崭新的排序后的列表。最重要的是,它不会破坏原来的数据,你可以随时拿着原样再排一次。
小提示:如果你只想在原列表上直接动手(比如“把这个列表排好,旧数据不要了”),可以用
列表.sort()方法,但那只能用于列表。
1. 基本用法:从小到大排一排
所有可迭代对象都能用,比如一堆数字:
numbers = [4, 1, 9, 3, 6] # 原始数字列表
sorted_numbers = sorted(numbers) # 排序后得到新列表
print(sorted_numbers) # 输出 [1, 3, 4, 6, 9]
print(numbers) # 输出 [4, 1, 9, 3, 6] 原列表纹丝不动
生活例子:你有一包零食的价格(元):[4, 1, 9, 3, 6],想从便宜到贵排列,sorted一下就能看到最便宜的1元,最贵的9元。
2. 降序排序:从大到小
只要加上参数reverse=True,就能让顺序反过来。
scores = [85, 92, 78, 90] # 考试成绩列表
sorted_scores = sorted(scores, reverse=True) # 从高到低排
print(sorted_scores) # 输出 [92, 90, 85, 78] 第一名92分
生活中的例子:班级月考后,你想知道谁最高分,谁最低分,用降序排一下,第一名就冒出来了。
3. 对字符串排序:按照字母顺序
字符串也可以排,但返回的是字符列表(每个字符单独出来)。按字母顺序(实际是按ASCII码,大写字母排在小写前面)。
name = "python" # 字符串
sorted_chars = sorted(name) # 排序后得到字符列表
print(sorted_chars) # 输出 ['h', 'n', 'o', 'p', 't', 'y']
# 如果你想要回一个字符串,可以用join拼接
sorted_str = ''.join(sorted_chars)
print(sorted_str) # 输出 "hnopty"
注意:大小写敏感,例如 "Banana" 和 "apple" 排序时,大写字母 'B'(ASCII 66)会排在小写 'a'(ASCII 97)前面,所以 "Banana" 会排在 "apple" 前面。如果你想要忽略大小写,可以用
key=str.lower。
4. 对字典排序:按键或按值
字典本身是无序的,但我们可以对它的键排序,或者对它的“键值对”按值排序。
4.1 只排字典的键
sorted(字典) 默认会返回一个排好序的键列表。比如你有一本班级年龄字典,想按名字(键)排序:
ages = {'小明':12, '小红':11, '小刚':13} # 姓名:年龄
sorted_keys = sorted(ages) # 对键排序
print(sorted_keys) # 输出 ['小明', '小刚', '小红'] 按字典序(汉字按Unicode码)
4.2 按字典的值排序
如果想按年龄从小到大排,需要获取字典的“键值对”列表(用.items()),然后用key参数指定按第二个元素(年龄)比较。
ages = {'小明':12, '小红':11, '小刚':13}
# .items() 返回类似 [('小明',12), ('小红',11), ('小刚',13)] 的列表
sorted_by_age = sorted(ages.items(), key=lambda x: x[1]) # 按年龄升序
print(sorted_by_age)
# 输出 [('小红', 11), ('小明', 12), ('小刚', 13)]
生活例子:体育课排队时,老师想按身高(值)从矮到高叫名字,用这个就能得到名字和身高的有序列表。
5. 自定义排序:用key参数为所欲为
sorted最强大的地方是key参数,它允许你指定一个“变换函数”,让排序依据这个函数的结果。例如按字符串长度排序:
words = ["apple", "pie", "banana", "kiwi"] # 单词列表
sorted_words = sorted(words, key=len) # 按长度升序
print(sorted_words) # 输出 ['pie', 'kiwi', 'apple', 'banana']
# pie长度3,kiwi长度4,apple长度5,banana长度6
更复杂的情况:比如你有学生成绩元组 (姓名, 分数),想按分数从高到低排序(降序),同时分数相同的按姓名排序(升序),可以用key返回一个元组:
student_scores = [('小明', 95), ('小红', 88), ('小刚', 95), ('小美', 88)]
# 先按分数降序,分数相同再按姓名升序
sorted_students = sorted(student_scores, key=lambda x: (-x[1], x[0]))
print(sorted_students)
# 输出 [('小明', 95), ('小刚', 95), ('小美', 88), ('小红', 88)]
# 注意:-x[1] 让分数变成负数,实现降序;然后x[0] 作为第二关键字
提示:key函数在排序前会作用于每个元素,根据返回值大小来定顺序。返回一个元组时,会依次比较元组内的每个部分。
6. 常见错误与注意事项
-
误区1:把
sorted的结果直接赋值给原变量,以为原对象变了items = [3,1,2] sorted(items) # 忘了赋值,结果丢了 print(items) # 还是 [3,1,2]正确做法:
items = sorted(items)或者用items.sort()。 -
误区2:对字典直接用
sorted,以为会返回排序后的字典
sorted(字典)返回的是键的列表,不是字典。如果需要排序后的“键值对列表”,用sorted(字典.items())。 -
误区3:想按字符串中的数字排序却直接排字符串
例如['a2', 'a10', 'a1']按字符串排会得到['a1', 'a10', 'a2'](因为'1'<'10'<'2'按字符比较),正确做法是用key提取数字:items = ['a2', 'a10', 'a1'] sorted_items = sorted(items, key=lambda x: int(x[1:])) # 提取后面的数字转int print(sorted_items) # ['a1', 'a2', 'a10'] -
误区4:在
key函数中使用可变类型(如列表)作为返回值
key应该返回可比较的不可变类型(数字、字符串、元组等)。例如不要用key=lambda x: x.sort()之类。 -
误区5:忽略
reverse与key的搭配
如果既要降序又要特殊规则,可以reverse=True,也可以像前面-x[1]那样取负值。但混合使用时注意逻辑。
7. 完整可运行示例:处理成绩单
下面是一个完整的小程序,模拟老师处理全班考试分数,按总分排名,并输出前五名。
# 学生成绩字典:姓名 -> (语文, 数学, 英语)
student_grades = {
'小明': (90, 85, 92),
'小红': (88, 90, 95),
'小刚': (92, 80, 88),
'小美': (85, 92, 90),
'小华': (95, 88, 80)
}
# 计算总分,并存储为列表
grades_list = [] # 用来存放 (姓名, 总分) 的元组
for name, scores in student_grades.items():
total = sum(scores) # 计算总分
grades_list.append((name, total)) # 添加元组
# 按总分降序排序(从高到低)
sorted_grades = sorted(grades_list, key=lambda x: x[1], reverse=True)
print("=== 成绩排名(前五名)===")
for rank, (name, total) in enumerate(sorted_grades[:5], start=1):
print(f"第{rank}名:{name},总分{total}分")
运行输出示例:
=== 成绩排名(前五名)===
第1名:小红,总分273分
第2名:小明,总分267分
第3名:小美,总分267分
第4名:小刚,总分260分
第5名:小华,总分263分
(注意:小明和小美总分相同,排序结果依赖于稳定排序,这里没有指定第二关键字,所以保持原顺序。)
8. 相关知识点
列表.sort()方法:如果你不需要保留原列表,直接在原列表上修改,用列表.sort()更高效(不创建新列表)。它和sorted的key、reverse参数用法完全一样。- lambda匿名函数:在
key里经常用的lambda x: x[1]是一个简短的函数,相当于def get_value(x): return x[1]。掌握lambda能让代码更简洁。 - 元组排序的比较规则:当key返回元组时,先比较第一个元素,相等再比较第二个,以此类推。
operator模块:提供itemgetter、attrgetter等函数,可以替代lambda,在某些场景下更高效(如sorted(grades_list, key=itemgetter(1)))。cmp参数(Python 2):在Python 3中cmp已经移除,全用key实现。若需自定义比较器,可以用functools.cmp_to_key转换,但不常用。
排序是编程中的基础操作,在CSP-J考试中经常出现在查找、去重、贪心等题目里。学会 sorted,很多问题都能迎刃而解。
例题精讲
执行以下代码后,变量 result 的值是什么? result = sorted([3, 1, 2])
sorted() 函数会直接修改原列表的顺序,而 list.sort() 则返回一个新列表。
给定一个字符串列表 words = ['apple', 'kiwi', 'banana', 'pear'],请按字符串长度从小到大排序,将结果存入变量 sorted_words。
words = ['apple', 'kiwi', 'banana', 'pear']
sorted_words = sorted(words, key=___)若要对列表 [5, 2, 8, 1] 进行降序排序,下列哪个写法是正确的?
有一个字典 scores = {'Alice': 88, 'Bob': 72, 'Cathy': 95},请按值(分数)从高到低排序,并输出排序后的 (姓名, 分数) 列表。
scores = {'Alice': 88, 'Bob': 72, 'Cathy': 95}
sorted_list = sorted(scores.items(), key=___, reverse=True)
print(sorted_list)