MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python列表的sorted函数临时排序

2023-02-191.2k 阅读

Python列表的sorted函数临时排序

sorted函数基础介绍

在Python编程语言中,sorted()函数是一个非常实用且常用的内置函数,主要用于对可迭代对象(如列表、元组、字典等)进行排序操作。当我们处理列表时,sorted()函数能够临时对列表中的元素进行排序,并返回一个新的已排序列表,而原列表保持不变。这与列表对象自身的sort()方法不同,sort()方法会直接在原列表上进行排序,改变原列表的顺序。

sorted()函数的基本语法如下:

sorted(iterable, key=None, reverse=False)

其中,iterable是必填参数,代表要进行排序的可迭代对象,在本文中主要关注列表;key是一个可选参数,用于指定一个函数,该函数会应用到每个元素上,以提供比较的依据;reverse也是可选参数,是一个布尔值,默认为False,表示升序排序,如果设置为True,则进行降序排序。

对简单列表进行排序

  1. 升序排序 最简单的应用场景就是对一个由数字组成的列表进行升序排序。例如:
num_list = [5, 2, 8, 1, 9]
sorted_num_list = sorted(num_list)
print(sorted_num_list)

在上述代码中,我们定义了一个列表num_list,然后使用sorted()函数对其进行排序,并将结果赋值给sorted_num_list。运行这段代码,输出结果为[1, 2, 5, 8, 9],原列表num_list的顺序并没有改变。

  1. 降序排序 如果我们希望对列表进行降序排序,只需要将reverse参数设置为True。例如:
num_list = [5, 2, 8, 1, 9]
sorted_num_list = sorted(num_list, reverse=True)
print(sorted_num_list)

运行上述代码,输出结果为[9, 8, 5, 2, 1],同样原列表num_list保持不变。

根据自定义函数进行排序(key参数的使用)

  1. 对字符串列表按长度排序 有时候,我们不仅仅需要对数字列表按数值大小排序,还可能需要根据其他规则对不同类型的列表进行排序。比如,对于一个字符串列表,我们可能希望按照字符串的长度进行排序。这时候就可以使用key参数。
str_list = ["apple", "banana", "cherry", "date"]
sorted_str_list = sorted(str_list, key=len)
print(sorted_str_list)

在这段代码中,我们将key参数设置为len函数,len函数用于获取字符串的长度。这样,sorted()函数会根据每个字符串的长度来对列表进行排序。运行结果为['date', 'apple', 'cherry', 'banana'],按照字符串长度从小到大排列。

  1. 对复杂对象列表进行排序 当列表中的元素是自定义的对象时,排序会稍微复杂一些。假设我们有一个表示学生的类,每个学生对象有姓名和成绩两个属性,我们希望根据成绩对学生列表进行排序。
class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score


students = [
    Student("Alice", 85),
    Student("Bob", 78),
    Student("Charlie", 92)
]


def get_score(student):
    return student.score


sorted_students = sorted(students, key=get_score)
for student in sorted_students:
    print(f"{student.name}: {student.score}")

在上述代码中,我们定义了一个Student类,然后创建了一个包含多个学生对象的列表。接着定义了一个get_score函数,用于获取学生对象的成绩。最后,在sorted()函数中,将key参数设置为get_score函数,这样就可以根据学生的成绩对列表进行排序了。运行结果会按照成绩从低到高输出学生的信息。

对嵌套列表进行排序

  1. 根据嵌套列表的某个元素排序 假设有一个嵌套列表,每个子列表包含两个元素,分别是姓名和年龄,我们希望根据年龄对这个嵌套列表进行排序。
people = [
    ["Alice", 25],
    ["Bob", 20],
    ["Charlie", 30]
]
sorted_people = sorted(people, key=lambda x: x[1])
print(sorted_people)

这里我们使用了lambda表达式来定义一个匿名函数,lambda x: x[1]表示取子列表的第二个元素(即年龄)作为排序依据。运行代码后,sorted_people会按照年龄从小到大排列。

  1. 多层嵌套列表的排序 如果嵌套列表更加复杂,例如每个子列表又包含多个子子列表,并且我们需要根据更深层次的某个元素进行排序。假设我们有一个表示班级学生成绩的嵌套列表,每个班级的学生成绩又以子列表形式存储,每个子列表包含学生姓名和该学生的总成绩,我们希望根据每个班级学生的平均成绩对班级进行排序。
classes = [
    [["Alice", 85, 90], ["Bob", 78, 82]],
    [["Charlie", 92, 88], ["David", 80, 85]],
    [["Eve", 75, 70], ["Frank", 68, 72]]
]


def get_average_score(class_students):
    total_score = 0
    student_count = 0
    for student in class_students:
        total_score += sum(student[1:])
        student_count += 1
    return total_score / student_count if student_count > 0 else 0


sorted_classes = sorted(classes, key=get_average_score)
for class_students in sorted_classes:
    print(f"Average score: {get_average_score(class_students)}")
    for student in class_students:
        print(f"{student[0]}: {sum(student[1:])}")
    print()

在这段代码中,我们首先定义了一个get_average_score函数,用于计算每个班级学生的平均成绩。然后在sorted()函数中,将key参数设置为这个函数,从而根据平均成绩对班级列表进行排序。运行代码后,会按照平均成绩从低到高输出每个班级及其学生的成绩信息。

sorted函数与其他数据结构结合使用

  1. 与元组结合 虽然元组是不可变的,但sorted()函数同样可以对元组进行排序,只不过返回的结果是一个列表。例如:
num_tuple = (5, 2, 8, 1, 9)
sorted_num_list = sorted(num_tuple)
print(sorted_num_list)

这里我们对一个数字元组使用sorted()函数,返回的sorted_num_list是一个已排序的列表。

  1. 与字典结合 对于字典,sorted()函数可以对字典的键或值进行排序。如果直接对字典使用sorted()函数,默认是对字典的键进行排序。
my_dict = {'c': 3, 'a': 1, 'b': 2}
sorted_keys = sorted(my_dict)
print(sorted_keys)

上述代码会输出排序后的字典键列表['a', 'b', 'c']。如果我们希望根据字典的值进行排序,可以这样做:

my_dict = {'c': 3, 'a': 1, 'b': 2}
sorted_items = sorted(my_dict.items(), key=lambda item: item[1])
print(sorted_items)

这里使用my_dict.items()获取字典的键值对,然后通过key=lambda item: item[1]根据值进行排序,返回的结果是一个包含键值对的列表,按照值从小到大排列。

sorted函数在实际项目中的应用场景

  1. 数据分析中的排序 在数据分析场景中,经常需要对数据进行排序以便更好地观察和分析。例如,在处理销售数据时,我们可能有一个列表,每个元素是一个包含产品名称、销售数量和销售额的子列表。我们可以根据销售额对这个列表进行排序,找出销售额最高的产品。
sales_data = [
    ["Product A", 100, 5000],
    ["Product B", 150, 7500],
    ["Product C", 80, 4000]
]
sorted_sales_data = sorted(sales_data, key=lambda x: x[2], reverse=True)
for data in sorted_sales_data:
    print(f"{data[0]}: {data[2]}")

这段代码根据销售额对销售数据进行降序排序,方便我们快速了解销售额排名情况。

  1. 搜索算法中的应用 在一些搜索算法中,排序是一个重要的预处理步骤。例如,在二分查找算法中,要求数据必须是有序的。如果我们从外部获取的数据是无序的列表,就可以使用sorted()函数先对其进行排序,然后再应用二分查找算法,提高查找效率。
def binary_search(sorted_list, target):
    low, high = 0, len(sorted_list) - 1
    while low <= high:
        mid = (low + high) // 2
        if sorted_list[mid] == target:
            return mid
        elif sorted_list[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1


num_list = [5, 2, 8, 1, 9]
sorted_num_list = sorted(num_list)
target = 8
index = binary_search(sorted_num_list, target)
if index != -1:
    print(f"Target {target} found at index {index}")
else:
    print(f"Target {target} not found")

在上述代码中,我们先使用sorted()函数对列表进行排序,然后应用二分查找算法查找目标值。

性能考虑

  1. 大数据量下的性能 当处理大数据量的列表时,sorted()函数的性能是一个需要考虑的因素。Python的sorted()函数在内部使用了一种高效的排序算法(通常是Timsort),这种算法在大多数情况下表现良好。然而,对于极其庞大的数据集,仍然可能存在性能瓶颈。在这种情况下,可以考虑使用更专业的排序算法库,或者分块处理数据等优化策略。 例如,假设我们有一个包含100万个随机整数的列表,对其进行排序:
import random
import time

big_list = [random.randint(1, 1000000) for _ in range(1000000)]
start_time = time.time()
sorted_big_list = sorted(big_list)
end_time = time.time()
print(f"Time taken: {end_time - start_time} seconds")

通过记录排序前后的时间,可以观察到sorted()函数在处理大数据量时所需的时间。如果时间过长,可以进一步探索优化方案。

  1. 多次排序的性能优化 如果在程序中需要多次对同一个列表进行不同规则的排序,每次都使用sorted()函数可能会导致性能下降。一种优化方法是在第一次排序后,根据后续的排序需求,通过对已排序列表进行少量的操作来实现新的排序。例如,如果先按某个属性升序排序,之后可能需要按相同属性降序排序,那么可以直接对升序排序列表使用reverse()方法,而不是再次调用sorted()函数。
students = [
    Student("Alice", 85),
    Student("Bob", 78),
    Student("Charlie", 92)
]


def get_score(student):
    return student.score


sorted_students_asc = sorted(students, key=get_score)
sorted_students_desc = sorted_students_asc.copy()
sorted_students_desc.reverse()
for student in sorted_students_desc:
    print(f"{student.name}: {student.score}")

在上述代码中,我们先对学生列表按成绩升序排序,然后通过复制并反转已排序列表,得到按成绩降序排序的结果,避免了再次调用sorted()函数进行降序排序,从而提高了性能。

常见问题与解决方法

  1. TypeError错误 当列表中的元素类型不一致且无法直接比较时,会出现TypeError错误。例如:
mixed_list = [5, "apple", 3]
try:
    sorted_mixed_list = sorted(mixed_list)
except TypeError as e:
    print(f"Error: {e}")

在这个例子中,列表mixed_list包含了整数和字符串,由于整数和字符串不能直接比较大小,所以会抛出TypeError。解决方法是确保列表中的元素类型一致,或者通过key参数指定一个合适的函数来统一比较的标准。

  1. 排序结果不符合预期 有时候排序结果可能不符合预期,这可能是因为没有正确设置key参数或者reverse参数。例如,在对复杂对象列表排序时,如果key函数返回的不是期望的比较依据,就会导致排序结果错误。
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y


points = [
    Point(1, 2),
    Point(3, 1),
    Point(2, 3)
]


def wrong_key(point):
    return point.x


# 这里应该根据y坐标排序,但是使用了错误的key函数
sorted_points = sorted(points, key=wrong_key)
for point in sorted_points:
    print(f"({point.x}, {point.y})")

在上述代码中,我们本意是根据y坐标对Point对象列表进行排序,但key函数错误地返回了x坐标,导致排序结果不符合预期。解决方法是仔细检查key函数的实现,确保返回的是正确的比较依据。

通过对Python列表的sorted()函数的深入探讨,我们了解了它的基本用法、在不同场景下的应用、性能考虑以及常见问题的解决方法。在实际编程中,合理运用sorted()函数可以大大提高代码的效率和可读性,帮助我们更好地处理数据。无论是简单的数据排序,还是复杂对象和嵌套结构的排序,sorted()函数都提供了灵活且强大的解决方案。希望通过本文的介绍,读者能够更加熟练地使用sorted()函数,为自己的Python编程工作带来便利。