Python 中 sorted 如何自定义比较逻辑

了解 Sorted 函数

Python 中的 sorted 函数可以对一个可迭代对象进行排序,并返回一个新的列表,其中包含已经按特定顺序排列的元素。sorted 函数可以按照元素的字典顺序或根据特定的排序函数对元素进行排序。

默认情况下,sorted 函数将使用 Python 自带的比较运算符(如 >、<、==)对元素进行排序。

data = [4, 2, 6, 7, 1, 3]

sorted_data = sorted(data)

print(sorted_data) # [1, 2, 3, 4, 6, 7]

以上代码对一个整数列表进行了排序,并将排序结果赋给了变量 sorted_data。由于 sorted 函数默认按照升序排列,输出的结果也是升序排列的。

自定义比较逻辑

使用 key 参数

除了默认的比较运算符外,sorted 函数还支持使用 key 参数来提供自定义的比较逻辑。key 参数应该接受一个函数,该函数接受一个元素并返回用于比较元素的键值。

例如,假设我们有一个字符串列表,想要根据每个字符串的长度对它们进行排序。可以使用 len 函数作为 key 参数来实现这一功能。

fruits = ['apple', 'banana', 'orange', 'kiwi', 'strawberry']

sorted_fruits = sorted(fruits, key=len)

print(sorted_fruits) # ['kiwi', 'apple', 'banana', 'orange', 'strawberry']

以上代码将一个水果列表按照每个字符串的长度进行排序。由于 len 函数是一个类似于键的东西,每个元素的长度都会先进行计算,然后根据这个键对元素进行排序。

使用 cmp_to_key 函数

如果要使用其他自定义比较函数,可以使用 functools.cmp_to_key 函数将这个函数转换为接受单个参数并输出可供排序的键的函数。

例如,假设我们有一个学生列表,每个学生都有一个名字和一个分数,我们想根据分数从高到低对学生进行排序。

import functools

class Student:

def __init__(self, name, score):

self.name = name

self.score = score

def __repr__(self):

return f'Student({self.name!r}, {self.score})'

def compare_students(a, b):

return b.score - a.score

students = [

Student('Alice', 89),

Student('Bob', 72),

Student('Charlie', 94),

Student('Dave', 85),

]

# `key` parameter

print(sorted(students, key=lambda s: s.score, reverse=True))

# `cmp_to_key` function

print(sorted(students, key=functools.cmp_to_key(compare_students)))

以上代码使用了两种方法来根据学生的分数对学生进行排序。首先,我们使用 lambda 表达式作为排序键。这个 lambda 表达式接受一个学生对象并返回该学生的分数。由于我们要实现按照降序排序,所以在默认的升序排序基础上指定了 reverse=True 参数。

然后,我们使用 functools.cmp_to_key 函数将我们定义的 compare_students 函数转换为一个接受单个参数并输出按照 compare_students 函数输出的键值进行排序的函数。在此示例中,compare_students 函数接受两个学生对象并返回它们之间的分数差。由于我们要按照降序排序,所以需要将结果反转。

使用 key 参数实现如何多条件排序

对于具有多个排序条件的情况,可以将多个函数传递给 key 参数。sorted 函数将通过按照提供的键函数的先后顺序对元素进行排序。如果有多个键函数返回相同的值,则根据您指定的顺序对它们进行比较。

例如,假设我们有一个学生列表,每个学生都有一个名字、一个分数和一个出生日期,我们想首先按照分数从高到低排序,然后按照出生日期排序(年龄较大的在前)。

import datetime

class Student:

def __init__(self, name, score, birthdate):

self.name = name

self.score = score

self.birthdate = birthdate

def __repr__(self):

return f'Student({self.name!r}, {self.score}, {self.birthdate})'

students = [

Student('Alice', 89, datetime.date(2000, 3, 14)),

Student('Bob', 72, datetime.date(2001, 5, 24)),

Student('Charlie', 94, datetime.date(1999, 12, 1)),

Student('Dave', 85, datetime.date(2003, 1, 8)),

]

def sort_key(student):

return (-student.score, student.birthdate)

sorted_students = sorted(students, key=sort_key)

for student in sorted_students:

print(student)

以上代码首先定义了一个包含名字、分数和出生日期属性的学生类。我们将使用这个类来生成一个学生对象列表。在 sort_key 函数中,我们按照分数的相反顺序(即从高到低)和出生日期的顺序返回了一个元组。最后,我们将排序键函数 sort_key 传递给 sorted 函数并将排序结果打印出来。

结论

在 Python 中,sorted 函数是一个非常有用的函数,它可以按照元素的字典顺序或根据特定的排序函数对元素进行排序。默认情况下,sorted 函数按照升序排列,但是可以使用 reverse 参数反转排列顺序。

如果需要使用自定义比较逻辑,可以使用 key 参数提供用于计算每个元素键的函数。在第一个示例中,我们使用 len 函数计算字符串的长度。在第二个示例中,我们使用 functools.cmp_to_key 函数将比较函数转换为键函数,这个函数接受两个参数并返回唯一的可排序键。

最后,我们讨论了如何在 sorted 函数的 key 参数中使用多个函数来实现多条件排序。通过在 sort_key 函数中返回一个元组,我们可以使用多个关键函数创建一个相对排序测试。

后端开发标签