Python 将给定列表的元素按大小排序(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在 Python 编程中,列表(List)是最基础且常用的容器类型之一。无论是处理用户数据、分析日志文件,还是构建复杂的应用程序,开发者常常需要将列表中的元素按特定规则 排序。例如,电商网站可能需要按价格对商品列表排序,数据分析时可能需要按时间戳对记录排序。掌握 Python 将给定列表的元素按大小排序 的方法,不仅能提升代码效率,还能为后续的逻辑处理打下坚实基础。
本文将从基础到进阶,系统讲解 Python 中列表排序的核心方法,并通过实际案例与代码示例,帮助读者逐步掌握这一技能。
一、基础排序:sorted() 与 sort() 的区别
Python 提供了两种核心方法来实现列表排序:sorted()
函数和 list.sort()
方法。它们的核心功能相同,但使用场景和特性有显著差异。
1.1 sorted()
函数:返回新列表,原列表不变
sorted()
是一个内置函数,接受一个可迭代对象(如列表)作为参数,并返回一个 新排序后的列表,而不会修改原列表。
示例代码:
original_list = [3, 1, 4, 1, 5, 9]
sorted_list = sorted(original_list)
print("原列表:", original_list) # 输出:原列表: [3, 1, 4, 1, 5, 9]
print("排序后的列表:", sorted_list) # 输出:排序后的列表: [1, 1, 3, 4, 5, 9]
1.2 list.sort()
方法:原地修改列表
sort()
是列表对象的一个方法,会直接 修改原列表,并返回 None
。因此,它适合在需要节省内存或无需保留原始数据时使用。
示例代码:
original_list = [3, 1, 4, 1, 5, 9]
original_list.sort()
print("修改后的列表:", original_list) # 输出:修改后的列表: [1, 1, 3, 4, 5, 9]
总结:
- 选择
sorted()
的场景: 需要保留原始列表,或需要同时保留原列表和排序后的结果。 - 选择
list.sort()
的场景: 内存有限,或明确不需要保留原列表。
二、自定义排序规则:key 参数的魔法
默认情况下,Python 的排序方法会按元素的自然顺序排序(如数字按大小、字符串按字母顺序)。但实际开发中,我们常常需要根据 自定义规则 排序。例如:
- 按字符串长度排序
- 按对象的某个属性排序
- 忽略大小写排序
此时,可以通过 key
参数指定一个函数,将列表中的每个元素映射为一个用于比较的值。
2.1 基础用法:按字符串长度排序
假设有一个字符串列表,需要按字符串长度从长到短排序:
words = ["apple", "Banana", "cherry", "date"]
sorted_words = sorted(words, key=lambda x: len(x))
print(sorted_words) # 输出:['date', 'apple', 'Banana', 'cherry']
解释:
lambda x: len(x)
是一个匿名函数,将每个字符串x
映射为它的长度。sorted()
根据这些长度值进行排序,因此最短的字符串(如 "date",长度为4)排在最前面。
2.2 多条件排序:元组的妙用
有时需要按多个条件排序,例如先按价格降序,再按名称升序。此时,可以将 key
函数返回一个元组:
products = [
{"name": "iPhone", "price": 999},
{"name": "Galaxy", "price": 899},
{"name": "Pixel", "price": 799},
{"name": "iPhone", "price": 1099}
]
sorted_products = sorted(products, key=lambda x: (-x["price"], x["name"]))
for product in sorted_products:
print(f"{product['name']}: ${product['price']}")
输出:
iPhone: $1099
iPhone: $999
Galaxy: $899
Pixel: $799
技巧:
- 负号
-
可以实现降序排序(默认升序)。 - 元组中的元素按顺序比较,因此先比较价格(降序),再比较名称(升序)。
2.3 对象排序:自定义类的 __lt__
方法
如果要排序的对象是自定义类的实例,可以通过定义 __lt__
(小于)方法,或使用 functools.total_ordering
装饰器,让 Python 知道如何比较对象。
示例:按学生成绩排序
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def __repr__(self):
return f"Student({self.name}, {self.score})"
students = [
Student("Alice", 85),
Student("Bob", 92),
Student("Charlie", 78)
]
sorted_by_score = sorted(students, key=lambda s: s.score)
print(sorted_by_score)
三、进阶技巧:稳定性与多条件排序
3.1 排序稳定性:相同元素的相对位置
排序算法的 稳定性 指:当多个元素的排序键相同时,它们的相对位置是否在排序后保持不变。
Python 的 sorted()
和 list.sort()
默认是稳定的,即相等元素的原始顺序会被保留。
示例:
data = [("Alice", 85), ("Bob", 85), ("Charlie", 90)]
sorted_data = sorted(data, key=lambda x: x[1])
print(sorted_data)
3.2 反向排序:reverse 参数
若需要降序排序,只需设置 reverse=True
:
numbers = [5, 2, 8, 1]
descending = sorted(numbers, reverse=True) # 输出:[8, 5, 2, 1]
3.3 多级排序:结合 itemgetter
和元组
当需要按多个字段排序时,可以使用 operator
模块的 itemgetter
函数,提升代码可读性:
from operator import itemgetter
users = [
{"name": "Alice", "age": 30, "score": 90},
{"name": "Bob", "age": 25, "score": 85},
{"name": "Charlie", "age": 30, "score": 95}
]
sorted_users = sorted(users, key=itemgetter("age", "score"), reverse=[False, True])
四、性能与选择:不同场景的最佳实践
4.1 时间复杂度与算法选择
Python 的排序算法基于 Timsort,其时间复杂度为 O(n log n),适用于绝大多数场景。但在特殊情况下,需注意以下细节:
- 小列表(<1000 元素): Timsort 的常数项较小,性能优异。
- 大列表(>1e6 元素): 需确保内存足够,避免因排序导致的性能瓶颈。
4.2 内存敏感场景:原地排序 vs 创建新列表
- 使用
sort()
的优势: 不额外占用内存,适合处理超大列表。 - 使用
sorted()
的优势: 可以保留原列表,适合需要多版本排序结果的场景。
4.3 自定义排序的优化技巧
- 预计算键值: 若
key
函数计算开销较大(如调用数据库查询),可预先缓存结果。 - 避免嵌套函数: 将
key
函数定义为独立函数,而非内联lambda
,以提升可读性。
五、实战案例:综合排序应用
5.1 案例需求
假设我们有一个电商平台的订单列表,需要按以下规则排序:
- 优先级: 未发货订单(
status="pending"
)排在已发货订单之前。 - 次要排序: 按订单创建时间降序排列。
5.2 实现代码
from datetime import datetime
orders = [
{"id": 1, "status": "shipped", "created_at": datetime(2023, 1, 1)},
{"id": 2, "status": "pending", "created_at": datetime(2023, 1, 3)},
{"id": 3, "status": "pending", "created_at": datetime(2023, 1, 2)},
]
sorted_orders = sorted(
orders,
key=lambda o: (
0 if o["status"] == "pending" else 1,
-o["created_at"].timestamp() # 降序
)
)
for order in sorted_orders:
print(order["id"], order["status"], order["created_at"])
输出:
2 pending 2023-01-03 00:00:00
3 pending 2023-01-02 00:00:00
1 shipped 2023-01-01 00:00:00
结论:掌握排序,掌控数据
通过本文的讲解,读者应该能够:
- 熟练使用
sorted()
和list.sort()
完成基础排序。 - 通过
key
参数和reverse
参数实现复杂排序逻辑。 - 根据场景选择最优的排序方法,并理解其性能特性。
排序是编程中的基础技能,但其应用场景远不止本文所列。例如,在机器学习中,特征排序可能影响模型效果;在算法竞赛中,排序可能是优化时间复杂度的关键。因此,建议读者通过实际项目不断练习,并探索更高级的排序技巧(如多线程排序、外部排序等)。
Python 的排序功能强大且灵活,只要掌握核心概念,就能在各类场景中游刃有余。希望本文能成为您学习 Python 的一个坚实起点!