位置: 文档库 > Python > Python学习小技巧之列表项排序的示例代码分享

Python学习小技巧之列表项排序的示例代码分享

斐迪南大公 上传于 2020-08-29 09:34

《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中列表排序的多种方法,包括基础排序、自定义排序规则、多级排序性能优化技巧及常见错误解决方案,通过大量示例代码帮助读者掌握从简单到复杂的排序场景。