Python排序技巧:sorted与lambda使用全解析
Python排序是数据处理中的重要环节。本文深入解析了Python中两种常用的排序方法:`sorted()`函数和`list.sort()`方法。`sorted()`函数适用于各种可迭代对象,它会返回一个新的排序列表,不改变原始数据。而`list.sort()`方法则直接在原列表上进行排序,节省内存空间。两者都支持使用`key`参数和`lambda`表达式自定义排序规则,无论是按元组元素、字符串长度,还是字典键值,都能灵活应对。此外,文章还介绍了如何利用`lambda`表达式实现多条件排序,例如先按部门升序,再按薪水降序,以及处理嵌套数据结构的排序技巧。掌握这些`sorted`与`lambda`的技巧,能让你在Python编程中更加高效地处理各种排序需求。
Python中实现排序最常用的是sorted()函数和list.sort()方法。1.sorted()不改变原始数据,返回新列表;2.list.sort()是原地排序,直接修改原列表;3.两者都支持key参数,常使用lambda表达式定义排序规则。例如:可使用lambda按元组的某个元素、字符串长度、字典键值等排序;4.多条件排序可通过返回元组实现,如先按部门升序再按薪水降序;5.对于嵌套结构,可结合lambda提取深层数据进行排序。二者选择上,若需保留原始数据或处理非列表数据用sorted(),内存敏感或需原地修改用list.sort()。
Python中实现排序,最常用的莫过于内置的sorted()
函数和列表自带的sort()
方法。它们都支持通过lambda
表达式来定义自定义的排序规则,让数据按照你真正想要的逻辑排列。

解决方案
在Python里,排序这件事儿,其实挺直观的。你手头要是有个序列,想把它排个序,最直接的办法就是用sorted()
函数。它不改变原始序列,而是返回一个新的、已排序的列表。这就像你把一堆散乱的文件复印一份,然后整理复印件,原件还是乱的。
# 基础排序:数字和字符串 numbers = [3, 1, 4, 1, 5, 9, 2, 6] sorted_numbers = sorted(numbers) print(f"默认数字排序: {sorted_numbers}") # 输出: [1, 1, 2, 3, 4, 5, 6, 9] words = ["banana", "apple", "cherry", "date"] sorted_words = sorted(words) print(f"默认字符串排序: {sorted_words}") # 输出: ['apple', 'banana', 'cherry', 'date'] # 反向排序 reversed_numbers = sorted(numbers, reverse=True) print(f"反向数字排序: {reversed_numbers}") # 输出: [9, 6, 5, 4, 3, 2, 1, 1]
那如果你的数据结构复杂一点,比如是个元组列表,你想按元组里的某个特定元素排序怎么办?这时候lambda
函数就登场了,它就像一个“临时工”函数,随用随写,特别方便。lambda
表达式通常用作sorted()
或list.sort()
的key
参数。key
参数接受一个函数,这个函数会在排序前对每个元素进行处理,然后用处理后的结果进行比较。

# 使用lambda按元组的第二个元素排序 students = [('Alice', 25, 'A'), ('Bob', 20, 'B'), ('Charlie', 30, 'C')] sorted_by_age = sorted(students, key=lambda student: student[1]) print(f"按年龄排序: {sorted_by_age}") # 输出: [('Bob', 20, 'B'), ('Alice', 25, 'A'), ('Charlie', 30, 'C')] # 按字符串长度排序 fruits = ["apple", "banana", "kiwi", "grapefruit"] sorted_by_length = sorted(fruits, key=lambda fruit: len(fruit)) print(f"按长度排序: {sorted_by_length}") # 输出: ['kiwi', 'apple', 'banana', 'grapefruit'] # 忽略大小写排序 names = ["Alice", "bob", "Charlie", "david"] sorted_case_insensitive = sorted(names, key=lambda name: name.lower()) print(f"忽略大小写排序: {sorted_case_insensitive}") # 输出: ['Alice', 'bob', 'Charlie', 'david']
至于列表自己的sort()
方法,它和sorted()
最大的区别在于它是“原地”排序,直接修改原列表,不返回新列表。这在处理非常大的列表时,能省点内存。
my_list = [5, 2, 8, 1, 9] my_list.sort() # 原地排序 print(f"列表原地排序: {my_list}") # 输出: [1, 2, 5, 8, 9] # list.sort() 也支持 key 和 reverse 参数 my_students = [('Alice', 25), ('Bob', 20)] my_students.sort(key=lambda s: s[1], reverse=True) print(f"列表原地按年龄倒序: {my_students}") # 输出: [('Alice', 25), ('Bob', 20)]
Python排序中的key
参数究竟有何魔力?
key
参数,在我看来,是Python排序机制里最优雅也最强大的一个设计。它不是直接拿元素本身去比较,而是先用你提供的key
函数处理一下每个元素,然后用处理后的“结果”去比较。这就像你在整理一堆书,你可能不想按书名首字母排,而是想按作者名字排,或者按出版年份排。key
函数就负责从每本书里“提取”出那个作者名或出版年份。

举个例子,假设你有一堆字典,代表着商品信息:
products = [ {'name': 'Laptop', 'price': 1200, 'stock': 10}, {'name': 'Mouse', 'price': 25, 'stock': 50}, {'name': 'Keyboard', 'price': 75, 'stock': 20}, {'name': 'Monitor', 'price': 300, 'stock': 5} ] # 按商品价格排序 sorted_by_price = sorted(products, key=lambda p: p['price']) print("按价格排序:") for p in sorted_by_price: print(p) # 输出会是:Mouse, Keyboard, Monitor, Laptop # 按库存量从高到低排序 sorted_by_stock_desc = sorted(products, key=lambda p: p['stock'], reverse=True) print("\n按库存量倒序:") for p in sorted_by_stock_desc: print(p) # 输出会是:Mouse, Keyboard, Laptop, Monitor
这里lambda p: p['price']
就告诉sorted()
,对于每个字典p
,我关心的是它的'price'
键对应的值。sorted()
就拿这些价格去比较。这种“映射-比较”的模式,让排序变得异常灵活。你甚至可以对一个自定义类的对象进行排序,只要key
函数能提取出你想要的比较依据。
class Item: def __init__(self, name, weight): self.name = name self.weight = weight def __repr__(self): # 方便打印 return f"Item('{self.name}', {self.weight}kg)" items = [Item('Stone', 50), Item('Feather', 0.1), Item('Book', 2)] # 按重量排序 sorted_items = sorted(items, key=lambda item: item.weight) print(f"\n按重量排序: {sorted_items}") # 输出: [Item('Feather', 0.1kg), Item('Book', 2kg), Item('Stone', 50kg)]
key
参数的强大之处在于它将“如何比较”的逻辑与“比较什么”的逻辑分离了。你无需写复杂的比较函数,只需告诉Python“我要用这个值来代表我的元素进行比较”,剩下的它就帮你搞定了。
sorted()
与list.sort()
:何时选择,如何权衡?
这俩兄弟,虽然都能排序,但用起来还是有些讲究的。我个人在日常编码中,大部分时候会优先考虑sorted()
,因为它不会改变原始数据。这种“非侵入性”或者说“纯函数”的特性,在很多场景下能避免一些意想不到的副作用,尤其是在函数式编程风格或需要保持原始数据完整性的时候。
sorted()
:- 返回新列表: 它总是创建一个新的已排序的列表,原始的可迭代对象保持不变。
- 通用性强: 不仅仅是列表,任何可迭代对象(如元组、字符串、集合、字典的键等)都可以用
sorted()
进行排序。 - 内存开销: 因为要创建新列表,所以对于非常大的数据集,可能会有额外的内存开销。
- 示例:
new_list = sorted(my_tuple)
list.sort()
:- 原地排序: 它直接修改列表本身,不返回任何值(返回
None
)。 - 仅限列表: 只能用于列表对象。
- 内存效率: 由于是原地操作,它通常在内存使用上更高效,对于内存敏感或超大型列表是首选。
- 示例:
my_list.sort()
- 原地排序: 它直接修改列表本身,不返回任何值(返回
什么时候用哪个?这其实是个权衡。
如果你需要保留原始列表,或者你的数据不是列表(比如你只想对一个元组排序然后得到一个新的列表),那么sorted()
是你的不二之选。它给你一个干净的新结果,不影响旧数据。
而如果你确定只需要排序列表本身,并且不介意它被修改,或者你正在处理一个内存非常大的列表,list.sort()
就显得更高效了。比如,你从数据库里捞出来一个巨大的列表,只想把它按某个字段排个序,然后接着处理,那么直接list.sort()
会比先复制再排序来得快。
一个常见的“坑”是,新手可能会写my_list = my_list.sort()
,然后发现my_list
变成了None
。记住,list.sort()
不返回列表,它修改的是原列表。
data_tuple = (5, 1, 9, 3) # data_tuple.sort() # 这会报错,因为元组没有sort方法 sorted_data = sorted(data_tuple) print(f"元组排序结果 (sorted): {sorted_data}") # 输出: [1, 3, 5, 9] print(f"原始元组: {data_tuple}") # 输出: (5, 1, 9, 3) - 保持不变 large_list = list(range(1000000, 0, -1)) # 假设这是一个非常大的列表 # sorted_large_list = sorted(large_list) # 这会创建一份拷贝,可能消耗更多内存 large_list.sort() # 更高效地原地排序 print(f"大型列表是否已排序 (部分检查): {large_list[:5]}...") # 输出: [1, 2, 3, 4, 5]...
在稳定性方面,Python的排序算法是稳定的。这意味着如果两个元素在排序key
值上相等,它们在排序后的相对顺序会保持不变。这在多条件排序时非常有用,比如你先按年龄排序,再按姓名排序,如果年龄相同,姓名就会保持原有的相对顺序。
多条件排序与复杂数据结构:lambda
函数的进阶应用
当你的排序需求变得复杂,比如需要按多个条件进行排序,或者处理的数据结构嵌套更深时,lambda
函数配合key
参数的威力就体现出来了。这就像你不仅仅想按作者排序,还想在作者相同的情况下,再按出版年份排序。
Python的key
函数可以返回一个元组。当key
函数返回元组时,sorted()
会按元组的第一个元素进行比较,如果第一个元素相同,就比较第二个元素,以此类推。这简直是为多条件排序量身定制的。
假设你有一个员工列表,你想先按部门排序,如果部门相同,再按薪水从高到低排序:
employees = [ {'name': 'Alice', 'dept': 'HR', 'salary': 60000}, {'name': 'Bob', 'dept': 'IT', 'salary': 80000}, {'name': 'Charlie', 'dept': 'HR', 'salary': 75000}, {'name': 'David', 'dept': 'IT', 'salary': 70000}, {'name': 'Eve', 'dept': 'HR', 'salary': 60000} ] # 先按部门升序,再按薪水降序 sorted_employees = sorted(employees, key=lambda emp: (emp['dept'], -emp['salary'])) # 注意:对数字使用负号可以实现降序排列,因为默认是升序。 # 或者使用itemgetter,但lambda更直接。 print("按部门升序,薪水降序排序的员工:") for emp in sorted_employees: print(emp) # 输出会是: # HR部门的Alice (60000), Eve (60000) - 薪水相同,保持原始相对顺序 # HR部门的Charlie (75000) # IT部门的Bob (80000) # IT部门的David (70000)
在这个例子中,lambda emp: (emp['dept'], -emp['salary'])
返回了一个元组。sorted()
会先比较'dept'
,如果'dept'
相同,再比较-emp['salary']
。因为我们希望薪水是降序,所以取了负值,这样数值越大,负值越小,在升序比较时反而排在前面。
处理更复杂的嵌套结构也是类似的。只要你的lambda
函数能“挖”出你想要的比较依据,无论数据藏得多深,排序都能搞定。
# 假设有课程和学生信息,按课程ID排序,然后按学生姓名排序 courses_data = [ {'course_id': 'CS101', 'students': [{'name': 'Zoe'}, {'name': 'Amy'}]}, {'course_id': 'MA202', 'students': [{'name': 'Bob'}, {'name': 'Carl'}]}, {'course_id': 'CS101', 'students': [{'name': 'David'}, {'name': 'Eve'}]} ] # 假设我们想按课程ID排序,然后对每个课程内部的学生按姓名排序 # 这需要两步操作,或者更复杂的结构,但如果只是排序最外层列表,可以这样: sorted_courses_by_id = sorted(courses_data, key=lambda c: c['course_id']) print("\n按课程ID排序:") for c in sorted_courses_by_id: print(c) # 输出: CS101, CS101, MA202 (课程ID相同,顺序可能不变) # 如果想对每个课程内的学生列表也排序,那需要单独处理 for course in courses_data: course['students'].sort(key=lambda s: s['name']) print("\n课程内学生按姓名排序后的课程数据:") for c in courses_data: print(c) # 输出: CS101 (Amy, Zoe), MA202 (Bob, Carl), CS101 (David, Eve)
这里展示了,对于嵌套结构,你可能需要组合使用sorted()
和list.sort()
,或者进行多步操作。lambda
函数在提取深层数据作为key
方面,提供了极大的便利。它避免了你需要为每个特定的排序需求都写一个完整的def
函数,使得代码更加简洁和即时。
今天关于《Python排序技巧:sorted与lambda使用全解析》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

- 上一篇
- GitHubCodespaces配置Golang容器加速指南

- 下一篇
- Golang错误处理,pkg/errors.Wrap使用详解
-
- 文章 · python教程 | 2小时前 |
- PyCharm界面详解:核心功能全解析
- 501浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- Python操作CAD文件,DXF格式全解析
- 355浏览 收藏
-
- 文章 · python教程 | 2小时前 |
- 未激活系统,PowerShell警告怎么关
- 449浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Pythonif语句入门实例详解
- 274浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python方差与标准差计算教程
- 134浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python中//运算符作用解析
- 174浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python泛型约束:组合类型技巧解析
- 106浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python操作PPT教程:python-pptx使用详解
- 195浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python快速处理Excel数据技巧
- 195浏览 收藏
-
- 文章 · python教程 | 3小时前 |
- Python中int是什么类型?
- 197浏览 收藏
-
- 文章 · python教程 | 4小时前 |
- Python列表高效垂直打印技巧
- 322浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 边界AI平台
- 探索AI边界平台,领先的智能AI对话、写作与画图生成工具。高效便捷,满足多样化需求。立即体验!
- 411次使用
-
- 免费AI认证证书
- 科大讯飞AI大学堂推出免费大模型工程师认证,助力您掌握AI技能,提升职场竞争力。体系化学习,实战项目,权威认证,助您成为企业级大模型应用人才。
- 421次使用
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 559次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 660次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 567次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览