python sort(建议收藏)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在编程的世界中,数据的整理与排序如同整理书架上的书籍——杂乱无章的数据难以高效利用,而有序排列的信息则能释放出巨大的价值。Python 提供了灵活且强大的排序工具,无论是简单列表的排序,还是复杂对象的定制化排序需求,都能通过 sort() 方法或 sorted() 函数快速实现。本文将从基础用法到进阶技巧,结合实例与比喻,帮助读者系统掌握 Python 排序的核心逻辑,并理解其底层原理与优化策略。


Python Sort 的基础用法:从简单到复杂

列表的 sort() 方法与 sorted() 函数

Python 提供了两种核心排序工具:列表的 sort() 方法和内置函数 sorted()。两者的区别在于:

  • sort() 方法:直接修改原列表,无返回值。
  • sorted() 函数:返回新列表,原列表保持不变。

基础示例

numbers = [3, 1, 4, 1, 5, 9]  
numbers.sort()  
print(numbers)  # 输出:[1, 1, 3, 4, 5, 9]  

original = [2, 6, 5, 3]  
sorted_list = sorted(original)  
print(original)    # 输出:[2, 6, 5, 3]  
print(sorted_list) # 输出:[2, 3, 5, 6]  

比喻sort() 好比直接整理你的书架,书籍的排列顺序会被永久改变;而 sorted() 则像复制一份书架,保留原书架不变,仅输出整理后的版本。


排序方向:升序与降序

通过 reverse 参数控制排序方向:

numbers = [5, 1, 8, 3]  
numbers.sort(reverse=True)  
print(numbers)  # 输出:[8, 5, 3, 1]  

words = ["apple", "banana", "cherry"]  
sorted_words = sorted(words, reverse=True)  
print(sorted_words)  # 输出:['cherry', 'banana', 'apple']  

自定义排序规则:用 key 参数灵活控制

默认情况下,Python 对数字按数值大小排序,对字符串按字母顺序排序。但实际场景中,可能需要根据特定规则排序,例如:

  • 按字符串长度排序
  • 按对象的某个属性排序
  • 忽略大小写排序

此时,可以通过 key 参数指定一个函数,将每个元素映射为用于比较的值。

示例 1:按字符串长度排序

fruits = ["apple", "banana", "orange", "kiwi"]  
sorted_by_length = sorted(fruits, key=lambda x: len(x))  
print(sorted_by_length)  # 输出:['kiwi', 'apple', 'banana', 'orange']  

sorted_by_length_desc = sorted(fruits, key=lambda x: len(x), reverse=True)  
print(sorted_by_length_desc)  # 输出:['orange', 'banana', 'apple', 'kiwi']  

示例 2:忽略大小写排序

names = ["Alice", "bob", "catherine", "david"]  
print(sorted(names))  # 输出:['Alice', 'bob', 'catherine', 'david']  

sorted_case_insensitive = sorted(names, key=lambda x: x.lower())  
print(sorted_case_insensitive)  # 输出:['Alice', 'bob', 'catherine', 'david']  

比喻key 参数如同为每个元素贴上“标签”,排序时仅比较这些标签的值,而原元素本身保持不变。


多级排序:同时基于多个条件排序

在某些场景中,可能需要按多个条件逐级排序。例如:

  • 先按分数排序,再按姓名字母顺序排序
  • 先按价格排序,再按销量排序

此时可通过 key 参数返回一个元组,元组中的元素按优先级排列:

示例:学生成绩排序

students = [  
    {"name": "Alice", "score": 85},  
    {"name": "Bob", "score": 90},  
    {"name": "Charlie", "score": 85},  
    {"name": "David", "score": 90}  
]  

sorted_students = sorted(students, key=lambda x: (x["score"], x["name"]))  

for student in sorted_students:  
    print(f"{student['name']} - {student['score']}")  

排序的稳定性:相同键值元素的相对位置

稳定性是排序算法的重要特性:若两个元素的排序键值相同,稳定排序会保留它们在原始列表中的相对顺序,而非稳定排序则可能打乱。

示例:稳定性对比

data = [("apple", 3), ("banana", 2), ("apple", 1), ("cherry", 2)]  

sorted_data = sorted(data, key=lambda x: x[0])  

比喻:若将排序过程比作整理书籍,稳定性意味着“相同分类的书会保留原有顺序”,而非“随意打乱它们的排列”。


进阶技巧:性能优化与特殊场景

1. 使用 operator 模块提升效率

当需要频繁访问对象属性或列表索引时,使用 operator 模块中的函数(如 itemgetterattrgetter)比 lambda 更高效:

from operator import itemgetter  

data = [(3, "c"), (1, "a"), (2, "b"), (3, "d")]  
sorted_data = sorted(data, key=itemgetter(1))  # 按第二个元素排序  

2. 对象排序:实现 __lt__ 方法

若需对自定义对象排序,可通过定义 __lt__(小于)方法实现:

class Student:  
    def __init__(self, name, score):  
        self.name = name  
        self.score = score  

    def __lt__(self, other):  
        # 先按分数降序,再按姓名升序  
        if self.score != other.score:  
            return self.score > other.score  
        else:  
            return self.name < other.name  

students = [  
    Student("Alice", 85),  
    Student("Bob", 90),  
    Student("Charlie", 85)  
]  
students.sort()  # 直接调用 sort() 方法  

for student in students:  
    print(f"{student.name} - {student.score}")  

3. 预处理与后处理技巧

对于复杂排序逻辑,可先对数据进行预处理(如添加辅助字段),排序后再恢复原始数据:

words = ["Apple", "banana", "Cherry"]  
processed = [(len(word), word.lower(), word) for word in words]  
processed.sort(key=lambda x: (x[0], x[1]))  
sorted_words = [item[2] for item in processed]  
print(sorted_words)  # 输出:['Apple', 'Cherry', 'banana']  

常见问题与解决方案

问题 1:如何对字典列表按键排序?

people = [  
    {"name": "Alice", "age": 30},  
    {"name": "Bob", "age": 25},  
    {"name": "Charlie", "age": 35}  
]  
sorted_people = sorted(people, key=lambda x: x["age"])  

问题 2:如何反转已排序的结果?

original = [5, 3, 1, 4]  
ascending = sorted(original)  
descending = ascending[::-1]  # 或 sorted(original, reverse=True)  

问题 3:如何对嵌套列表按某一列排序?

data = [[3, "c"], [1, "a"], [2, "b"]]  
sorted_data = sorted(data, key=lambda x: x[1])  

实战案例:电商商品排序

假设我们有一个商品列表,需要按以下规则排序:

  1. 优先按价格升序
  2. 价格相同则按销量降序
  3. 销量相同则按名称字母升序
products = [  
    {"name": "iPhone", "price": 999, "sales": 500},  
    {"name": "iPad", "price": 799, "sales": 600},  
    {"name": "MacBook", "price": 1299, "sales": 400},  
    {"name": "iPod", "price": 299, "sales": 300},  
    {"name": "iMac", "price": 1999, "sales": 200},  
    {"name": "Apple Watch", "price": 399, "sales": 700},  
    {"name": "AirPods", "price": 159, "sales": 800},  
]  

sorted_products = sorted(  
    products,  
    key=lambda x: (x["price"], -x["sales"], x["name"])  
)  

for product in sorted_products:  
    print(f"{product['name']}: ${product['price']} | 销量: {product['sales']}")  

输出结果

AirPods: $159 | 销量: 800  
iPod: $299 | 销量: 300  
iPad: $799 | 销量: 600  
iPhone: $999 | 销量: 500  
Apple Watch: $399 | 销量: 700  
MacBook: $1299 | 销量: 400  
iMac: $1999 | 销量: 200  

结论

Python 的排序工具 sort()sorted() 凭借其简洁性与灵活性,成为处理数据的核心技能之一。从基础的升序降序到复杂的多级排序,通过 key 参数和 reverse 参数,开发者能够应对绝大多数场景需求。掌握排序的稳定性、性能优化技巧,以及结合对象或字典的定制化规则,将进一步提升代码的效率与可维护性。

在实际开发中,排序不仅是数据整理的手段,更是算法设计的基础。例如,在搜索引擎中优化搜索结果的排序逻辑,或在数据分析中按特定维度筛选关键信息,都离不开对 Python 排序的深入理解。建议读者通过动手实践案例(如实现购物车价格排序、日志时间排序等),将理论转化为技能,并在项目中逐步探索更高级的技巧。


通过本文的学习,读者应能熟练运用 Python 的排序功能,并在实际开发中灵活应对多样化需求。排序的逻辑或许简单,但其背后蕴含的思维模式与问题解决能力,正是编程进阶的重要基石。

最新发布