ZetCode

Python sorted 函数

上次修改时间:2025 年 4 月 11 日

本综合指南探讨 Python 的 sorted 函数,该函数从可迭代对象中的项目返回一个新的排序列表。我们将介绍基本用法、自定义排序以及对各种数据结构进行排序的实际示例。

基本定义

sorted 函数从可迭代对象中的项目返回一个新的排序列表。与 list.sort() 不同,它可以与任何可迭代对象一起使用,并返回一个新列表,而不是就地修改。

主要特征:接受任何可迭代对象,返回一个新列表,通过 keyreverse 参数支持自定义排序。 它是稳定的(保持相等元素的相对顺序)。

基本排序

这是一个简单的用法,展示了 sorted 如何与不同的可迭代类型一起工作以及 reverse 参数的效果。

basic_sorted.py
# Sorting a list
numbers = [3, 1, 4, 1, 5, 9, 2]
print(sorted(numbers))  # [1, 1, 2, 3, 4, 5, 9]

# Sorting a tuple
letters = ('b', 'a', 'd', 'c')
print(sorted(letters))  # ['a', 'b', 'c', 'd']

# Reverse sorting
print(sorted(numbers, reverse=True))  # [9, 5, 4, 3, 2, 1, 1]

此示例显示了 sorted 与不同的可迭代类型一起使用。 它始终返回一个列表,无论输入类型如何。 reverse 参数控制排序顺序。

请注意,字符串按字典顺序(ASCII/Unicode 顺序)排序。 由于 sorted 创建新列表,因此原始可迭代对象保持不变。

使用 Key 函数自定义排序

key 参数允许自定义排序逻辑。 此示例显示了按字符串长度排序、不区分大小写的排序以及使用 lambda 函数。

key_sorted.py
words = ["apple", "Banana", "cherry", "date"]
print(sorted(words))  # ['Banana', 'apple', 'cherry', 'date'] (case-sensitive)
print(sorted(words, key=lambda x: x.lower()))  # ['apple', 'Banana', 'cherry', 'date']

# Sort by length
print(sorted(words, key=len))  # ['date', 'apple', 'Banana', 'cherry']

# Sort list of tuples by second element
pairs = [(1, 'one'), (3, 'three'), (2, 'two')]
print(sorted(pairs, key=lambda x: x[1]))  # [(1, 'one'), (3, 'three'), (2, 'two')]

key 函数在比较之前转换每个元素。 在这里,我们使用 str.lower 进行不区分大小写的排序,并使用 len 进行基于长度的排序。

Lambda 函数通常与 sorted 一起使用,用于简单的自定义排序逻辑。 转换不会影响结果中的实际值。

排序复杂对象

此示例演示如何使用基于属性的排序以及 key 参数对字典或自定义类等复杂对象进行排序。

object_sorted.py
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __repr__(self):
        return f"Person({self.name}, {self.age})"

people = [
    Person("Alice", 32),
    Person("Bob", 25),
    Person("Charlie", 40)
]

# Sort by age
print(sorted(people, key=lambda p: p.age))
# [Person(Bob, 25), Person(Alice, 32), Person(Charlie, 40)]

# Sort by name length
print(sorted(people, key=lambda p: len(p.name)))
# [Person(Bob, 25), Person(Alice, 32), Person(Charlie, 40)]

对于自定义对象,我们通常使用 lambda 函数来提取排序键。 在这里,我们按年龄和姓名长度对 Person 实例进行排序。

相同的方法适用于字典或任何可以定义键提取函数的对象。 原始对象保持不变。

稳定排序属性

Python 的 sorted 是稳定的,这意味着具有相等键的项目保持其原始相对顺序。 此示例演示了多级排序。

stable_sorted.py
# List of tuples (grade, name)
students = [
    ('B', 'Alice'),
    ('A', 'Bob'),
    ('C', 'Charlie'),
    ('A', 'David')
]

# Sort by grade (primary) and name (secondary)
sorted_students = sorted(students, key=lambda x: x[1])  # Sort by name first
sorted_students = sorted(sorted_students, key=lambda x: x[0])  # Then by grade

print(sorted_students)
# [('A', 'Bob'), ('A', 'David'), ('B', 'Alice'), ('C', 'Charlie')]

要按多个条件排序,我们按照重要性的相反顺序执行排序。 在这里,我们首先按姓名排序,然后按年级排序,并在年级内保持姓名顺序。

稳定性保证意味着不会不必要地重新排列相等的元素。 此属性对于可预测的多级排序至关重要。

性能注意事项

此示例比较了 sortedlist.sort() 的性能,并演示了使用不同键函数对大型数据集进行排序。

performance_sorted.py
import timeit
import random

# Generate large dataset
data = [random.randint(0, 1000) for _ in range(10000)]

def test_sorted():
    return sorted(data)

def test_sort_method():
    lst = list(data)
    lst.sort()
    return lst

def test_complex_key():
    return sorted(data, key=lambda x: (x % 10, x // 10))

print("sorted():", timeit.timeit(test_sorted, number=100))
print("list.sort():", timeit.timeit(test_sort_method, number=100))
print("Complex key:", timeit.timeit(test_complex_key, number=100))

sortedlist.sort() 稍慢,因为它必须创建一个新列表。 复杂的键函数会增加与其复杂性成正比的开销。

对于大型数据集,请考虑是否需要新列表或可以就地修改。 优化性能关键型排序操作的键函数。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程