Python学习小技巧之列表项排序的示例代码分享
《Python学习小技巧之列表项排序的示例代码分享》
在Python编程中,列表(List)作为最常用的数据结构之一,其排序操作是开发者必须掌握的核心技能。无论是处理用户输入、分析数据集还是优化算法,列表排序的效率与准确性直接影响程序性能。本文将通过系统化的示例代码,深入解析Python中列表排序的多种方法,涵盖内置函数、自定义排序规则、多级排序等场景,帮助读者从入门到进阶掌握这一关键技能。
一、基础排序:sorted()与list.sort()
Python提供了两种基础的列表排序方式:内置函数sorted()
和列表方法list.sort()
。两者的核心区别在于是否修改原列表。
1.1 sorted()函数:返回新列表
sorted()
函数接受任意可迭代对象作为输入,返回一个新的已排序列表,原列表保持不变。其基本语法为:
sorted(iterable, key=None, reverse=False)
示例1:对数字列表升序排序
numbers = [3, 1, 4, 1, 5, 9, 2]
sorted_numbers = sorted(numbers)
print(sorted_numbers) # 输出: [1, 1, 2, 3, 4, 5, 9]
print(numbers) # 输出: [3, 1, 4, 1, 5, 9, 2](原列表未改变)
示例2:对字符串列表降序排序
fruits = ['apple', 'banana', 'cherry', 'date']
sorted_fruits = sorted(fruits, reverse=True)
print(sorted_fruits) # 输出: ['date', 'cherry', 'banana', 'apple']
1.2 list.sort()方法:原地修改
list.sort()
是列表对象的方法,直接修改原列表,不返回新列表。语法为:
list.sort(key=None, reverse=False)
示例3:原地排序数字列表
numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort()
print(numbers) # 输出: [1, 1, 2, 3, 4, 5, 9]
示例4:原地降序排序字符串列表
fruits = ['apple', 'banana', 'cherry', 'date']
fruits.sort(reverse=True)
print(fruits) # 输出: ['date', 'cherry', 'banana', 'apple']
二、自定义排序规则:key参数详解
当默认的排序规则无法满足需求时,可通过key
参数指定排序依据。该参数接受一个函数,该函数会被应用到每个元素上,排序基于函数的返回值进行。
2.1 按字符串长度排序
示例5:对字符串列表按长度升序排序
words = ['apple', 'banana', 'cherry', 'date']
sorted_words = sorted(words, key=len)
print(sorted_words) # 输出: ['date', 'apple', 'banana', 'cherry']
示例6:使用lambda表达式简化代码
words = ['apple', 'banana', 'cherry', 'date']
sorted_words = sorted(words, key=lambda x: len(x))
print(sorted_words) # 输出同上
2.2 按元组的第二个元素排序
示例7:对元组列表按第二个元素排序
tuples = [(1, 'one'), (3, 'three'), (2, 'two')]
sorted_tuples = sorted(tuples, key=lambda x: x[1])
print(sorted_tuples) # 输出: [(1, 'one'), (3, 'three'), (2, 'two')](按字符串排序)
更实用的场景是按数值排序:
tuples = [(1, 3), (3, 1), (2, 2)]
sorted_tuples = sorted(tuples, key=lambda x: x[1])
print(sorted_tuples) # 输出: [(3, 1), (2, 2), (1, 3)]
2.3 按对象属性排序
当列表包含自定义对象时,可通过key
访问对象属性进行排序。
示例8:定义Person类并按年龄排序
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
people = [
Person('Alice', 25),
Person('Bob', 20),
Person('Charlie', 30)
]
# 按年龄升序排序
sorted_people = sorted(people, key=lambda p: p.age)
for person in sorted_people:
print(f"{person.name}: {person.age}")
# 输出:
# Bob: 20
# Alice: 25
# Charlie: 30
三、多级排序:结合多个key
实际应用中常需根据多个条件排序。Python可通过元组或自定义函数实现多级排序。
3.1 使用元组作为key
示例9:先按长度排序,长度相同按字母顺序排序
words = ['apple', 'banana', 'cherry', 'date', 'fig']
sorted_words = sorted(words, key=lambda x: (len(x), x))
print(sorted_words) # 输出: ['fig', 'date', 'apple', 'banana', 'cherry']
3.2 复杂多级排序:字典列表
示例10:对字典列表先按'age'降序,再按'name'升序
data = [
{'name': 'Alice', 'age': 25},
{'name': 'Bob', 'age': 20},
{'name': 'Charlie', 'age': 25}
]
# 方法1:使用元组作为key(注意reverse对整体的影响)
sorted_data = sorted(data, key=lambda x: (-x['age'], x['name']))
# 方法2:分步排序(更灵活)
# 先按name升序
data.sort(key=lambda x: x['name'])
# 再按age降序(稳定排序保留之前顺序)
data.sort(key=lambda x: x['age'], reverse=True)
for item in sorted_data:
print(item)
# 输出:
# {'name': 'Charlie', 'age': 25}
# {'name': 'Alice', 'age': 25}
# {'name': 'Bob', 'age': 20}
四、性能优化:大规模数据排序
对于大规模数据,排序性能成为关键。Python的Timsort算法(混合了归并排序和插入排序)在大多数情况下表现优异,但仍有优化空间。
4.1 避免不必要的key计算
示例11:缓存key计算结果
from functools import partial
# 原始方式(每次比较都计算key)
data = [{'id': i, 'value': str(i)*1000} for i in range(10000)]
sorted_data = sorted(data, key=lambda x: len(x['value']))
# 优化方式:预先计算key
def get_key(item):
return len(item['value'])
sorted_data = sorted(data, key=get_key) # 函数只调用一次
4.2 使用numpy进行数值排序
对于纯数值数据,numpy的排序方法更快:
import numpy as np
arr = np.random.rand(1000000)
sorted_arr = np.sort(arr) # 比Python内置排序快数倍
五、常见错误与解决方案
5.1 错误1:修改不可变类型
示例12:尝试对元组列表排序
tuples = [(1, 2), (3, 4)]
tuples.sort() # 报错: 'tuple' object does not support item assignment
# 解决方案:转换为列表或使用sorted()
sorted_tuples = sorted(tuples)
5.2 错误2:key函数返回不可比较类型
示例13:key返回字典导致错误
data = [{'a': 1}, {'a': 2}]
sorted(data, key=lambda x: x) # 报错: unhashable type: 'dict'
# 解决方案:指定可比较的属性
sorted(data, key=lambda x: x['a'])
5.3 错误3:混合类型排序
示例14:数字和字符串混合列表
mixed = [1, '2', 3, '4']
sorted(mixed) # 报错: TypeError
# 解决方案:统一类型或自定义key
sorted(mixed, key=lambda x: str(x)) # 全部转为字符串比较
六、进阶技巧:装饰-排序-去装饰模式
当排序逻辑复杂时,可采用"装饰-排序-去装饰"模式(DSU模式):
示例15:按字符串中数字排序
files = ['file1.txt', 'file10.txt', 'file2.txt']
# 装饰:提取数字并转换为元组
decorated = [(int(f[4:-4]), f) for f in files if f.startswith('file') and f.endswith('.txt')]
# 排序
decorated.sort()
# 去装饰
sorted_files = [f for (num, f) in decorated]
print(sorted_files) # 输出: ['file1.txt', 'file2.txt', 'file10.txt']
更简洁的写法(使用zip):
files = ['file1.txt', 'file10.txt', 'file2.txt']
numbers = [int(f[4:-4]) for f in files]
sorted_files = [f for _, f in sorted(zip(numbers, files))]
print(sorted_files) # 输出同上
七、实际应用案例
7.1 成绩单排序
示例16:按总分降序,总分相同按数学成绩降序
students = [
{'name': 'Alice', 'math': 90, 'english': 85},
{'name': 'Bob', 'math': 80, 'english': 95},
{'name': 'Charlie', 'math': 90, 'english': 80}
]
sorted_students = sorted(students, key=lambda x: (-(x['math'] + x['english']), -x['math']))
for student in sorted_students:
print(f"{student['name']}: 数学{student['math']}, 英语{student['english']}, 总分{student['math']+student['english']}")
# 输出:
# Alice: 数学90, 英语85, 总分175
# Charlie: 数学90, 英语80, 总分170
# Bob: 数学80, 英语95, 总分175
7.2 日志文件按时间排序
示例17:解析日志行中的时间戳并排序
import re
from datetime import datetime
logs = [
"[2023-01-02 10:00:00] INFO: System started",
"[2023-01-01 09:30:00] ERROR: Critical failure",
"[2023-01-02 08:15:00] WARNING: Disk full"
]
def parse_time(log):
time_str = re.search(r'\[(.*?)\]', log).group(1)
return datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
sorted_logs = sorted(logs, key=parse_time)
for log in sorted_logs:
print(log)
# 输出:
# [2023-01-01 09:30:00] ERROR: Critical failure
# [2023-01-02 08:15:00] WARNING: Disk full
# [2023-01-02 10:00:00] INFO: System started
八、总结与最佳实践
1. 优先使用sorted()
函数,除非需要原地修改列表
2. 简单排序直接使用key
参数,复杂逻辑考虑DSU模式
3. 对于自定义对象,实现__lt__
等方法可简化排序代码
4. 大规模数据考虑使用numpy或pandas的排序功能
5. 始终注意类型一致性,避免混合不可比较的类型
6. 多级排序时,元组key的顺序决定了优先级
通过系统掌握这些技巧,开发者能够高效处理各种排序需求,写出更专业、更高效的Python代码。
关键词:Python列表排序、sorted函数、list.sort方法、key参数、多级排序、DSU模式、性能优化
简介:本文详细介绍了Python中列表排序的多种方法,包括基础排序、自定义排序规则、多级排序、性能优化技巧及常见错误解决方案,通过大量示例代码帮助读者掌握从简单到复杂的排序场景。