当前位置:首页 > 文章列表 > 文章 > python教程 > Python排序技巧:sorted与lambda使用全解析

Python排序技巧:sorted与lambda使用全解析

2025-07-13 18:33:28 0浏览 收藏

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与lambda

Python中实现排序,最常用的莫过于内置的sorted()函数和列表自带的sort()方法。它们都支持通过lambda表达式来定义自定义的排序规则,让数据按照你真正想要的逻辑排列。

怎样用Python实现排序?sorted与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参数接受一个函数,这个函数会在排序前对每个元素进行处理,然后用处理后的结果进行比较。

怎样用Python实现排序?sorted与lambda
# 使用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函数就负责从每本书里“提取”出那个作者名或出版年份。

怎样用Python实现排序?sorted与lambda

举个例子,假设你有一堆字典,代表着商品信息:

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容器加速指南GitHubCodespaces配置Golang容器加速指南
上一篇
GitHubCodespaces配置Golang容器加速指南
Golang错误处理,pkg/errors.Wrap使用详解
下一篇
Golang错误处理,pkg/errors.Wrap使用详解
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    511次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    498次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • AI边界平台:智能对话、写作、画图,一站式解决方案
    边界AI平台
    探索AI边界平台,领先的智能AI对话、写作与画图生成工具。高效便捷,满足多样化需求。立即体验!
    411次使用
  • 讯飞AI大学堂免费AI认证证书:大模型工程师认证,提升您的职场竞争力
    免费AI认证证书
    科大讯飞AI大学堂推出免费大模型工程师认证,助力您掌握AI技能,提升职场竞争力。体系化学习,实战项目,权威认证,助您成为企业级大模型应用人才。
    421次使用
  • 茅茅虫AIGC检测:精准识别AI生成内容,保障学术诚信
    茅茅虫AIGC检测
    茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
    559次使用
  • 赛林匹克平台:科技赛事聚合,赋能AI、算力、量子计算创新
    赛林匹克平台(Challympics)
    探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
    660次使用
  • SEO  笔格AIPPT:AI智能PPT制作,免费生成,高效演示
    笔格AIPPT
    SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
    567次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码