左手编程,右手年华。大家好,我是一点,关注我,带你走入编程的世界。
公众号:一点sir,关注领取python编程资料
在Python中,列表排序是一项基础而重要的任务,它允许你对一系列元素进行有序排列。Python提供了多种内置方法来实现列表的排序,这些方法既适用于简单的数据类型,也适用于复杂的对象结构。
使用 sort()
方法
sort()
是列表对象的一个方法,它对列表内的元素进行原地排序,这意味着原始列表会直接被修改。
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
numbers.sort() # 列表原地排序
print(numbers) # 输出: [1, 1, 2, 3, 4, 5, 6, 9]
列表 numbers
包含了多个整数。调用 sort()
方法后,列表中的元素按照升序排列。注意,排序是原地进行的,所以 numbers
列表本身被修改了。
sort()
方法使用一种称为蒂姆排序(Timsort)的算法,它是对二叉树排序(一种自适应排序)和插入排序的优化。蒂姆排序的平均和最坏情况时间复杂度都是O(nlogn),其中n是列表的长度。
优点:
原地排序,不需要额外的内存分配。
对于部分排序的列表或具有一定顺序的列表,蒂姆排序非常高效。
缺点:
如果列表已经排序或接近排序状态,使用 sort()
方法会比 sorted()
多消耗一些内存。
使用 sorted()
函数
sorted()
是一个内置函数,它可以对任何可迭代对象进行排序,并返回一个新的排序后的列表,原始的可迭代对象不会被修改。
示例:
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_numbers = sorted(numbers) # 返回一个新的排序列表
print(sorted_numbers) # 输出: [1, 1, 2, 3, 4, 5, 6, 9]
print(numbers) # 原始列表不变: [3, 1, 4, 1, 5, 9, 2, 6]
numbers
列表被用作输入,但 sorted()
函数返回了一个新的列表 sorted_numbers
,原始的 numbers
列表保持不变。
sorted()
函数同样使用蒂姆排序算法,因此它的时间复杂度也是O(nlogn)。然而,由于它返回一个新的列表,所以需要额外的内存空间。
优点:
保持原始列表不变。
对于需要排序结果并保留原始数据的情况非常适用。
缺点:
需要额外的内存来存储新列表。
使用 key
参数进行排序
sort()
和 sorted()
都接受一个 key
参数,该参数允许你提供一个函数,用于从可迭代对象的每个元素中提取一个用于排序比较的值。
示例:
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def __repr__(self):
return f"{self.name} - {self.grade}"
students = [
Student("John", "A"),
Student("Jane", "B"),
Student("Jim", "A")
]
sorted_students = sorted(students, key=lambda x: x.grade)
print(sorted_students)
# 输出: [Jane - B, Jim - A, John - A]
在这个示例中,我们有一个 Student
类,它有两个属性:name
和 grade
。使用 sorted()
函数并通过 key
参数传递一个 lambda 函数,我们可以根据学生的 grade
对象进行排序。结果列表 sorted_students
首先按照成绩排序,同名的成绩则按照原始顺序排列。
使用 key
参数不会改变排序算法的时间复杂度,它仍然是O(nlogn)。但是,使用 key
可能会增加一些计算开销,因为需要对每个元素应用 key
函数。
优点:
提供了根据对象的某个属性进行排序的灵活性。
缺点:
对于每个元素的 key
函数调用会增加额外的计算。
使用 reverse
参数进行降序排序
sort()
和 sorted()
方法都接受一个 reverse
参数,当我们设置 reverse=True
时,排序将按照降序进行。
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_numbers_desc = sorted(numbers, reverse=True) # 降序排序
print(sorted_numbers_desc) # 输出: [9, 6, 5, 4, 3, 2, 1, 1]
我们使用 sorted()
函数并设置 reverse=True
,这使得排序结果按照降序排列。生成的列表 sorted_numbers_desc
包含了从大到小排列的数字。
是的,Python的operator
模块可以用于列表排序,尤其是在你需要根据对象的某个属性或者基于函数返回值进行复杂排序时。operator
模块提供了一个名为itemgetter
的函数,它可以用来获取对象的特定项,通常与sorted()
函数一起使用进行排序。
使用operator.itemgetter
进行排序
operator.itemgetter
是一个函数,它返回一个函数,这个返回的函数接受一个可迭代对象并返回你请求的那个项。这在排序列表中的复杂对象时非常有用。
比如说假设你有一个学生列表,每个学生都有多个属性,你想要基于学生的某个特定属性(如年龄或成绩)进行排序。
from operator import itemgetter
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade
def __repr__(self):
return f"{self.name}: {self.age}, {self.grade}"
# 创建一个学生列表
students = [
Student("John", 20, "A"),
Student("Jane", 18, "B"),
Student("Jim", 19, "B+"),
]
# 使用 itemgetter 按年龄排序
students_sorted_by_age = sorted(students, key=itemgetter(age))
print(students_sorted_by_age)
# 使用 itemgetter 按成绩排序
students_sorted_by_grade = sorted(students, key=itemgetter(grade))
print(students_sorted_by_grade)
对于上面的例子,我们首先定义了一个Student
类,然后创建了一个学生列表。我们使用operator.itemgetter
来创建一个用于获取学生年龄和成绩的函数,并将其作为sorted()
函数的key
参数。这样,我们就可以根据学生的年龄或成绩对列表进行排序。
使用operator.itemgetter
进行排序的性能通常与内置的sorted()
函数相当,因为排序算法(蒂姆排序)和时间复杂度(O(nlogn))是相同的。主要的性能开销来自于为每个列表项调用itemgetter
函数以获取相应的属性值。
注意事项
当你使用itemgetter
对对象列表进行排序时,记住列表中的所有对象必须具有用于排序的相同属性。
如果你只是对内置数据类型(如整数、字符串等)的列表进行排序,通常不需要使用operator
模块,直接使用sorted()
函数就足够了。
排序总结
在大多数情况下,Python的内置排序方法提供了良好的性能,sort()
和sorted()
足够可以应付大多数情况,其他的排序算法大概的了解就可以了。具体怎么使用就可你自己的实际情况了,当然如果你高兴,自己写排序方法也可以,什么冒泡排序,快速排序,堆排序等等,看你高兴吧,先说这么多吧,拜拜!