Python key排序
在使用 Python 进行排序操作时,经常会遇到按照自定义规则进行排序的需求。Python 提供了 sort
和 sorted
函数来实现排序,其中的 key
参数可以用来指定排序规则。本篇文章将详细介绍 key
排序的相关知识,包括用法、示例和实际应用。
1. 普通排序 vs. key排序
在 Python 中,普通排序是按照元素的大小(默认是升序)进行排序。例如,对一个整数列表进行排序:
nums = [5, 2, 9, 1, 7]
nums.sort()
print(nums) # 输出:[1, 2, 5, 7, 9]
key排序是按照自定义规则对元素进行排序。可以使用 key
参数来指定一个函数,这个函数会接受列表中的每个元素,并返回一个用来进行排序的关键字。根据关键字进行排序后的结果将作为最终排序的结果。例如,按照元素的绝对值进行排序:
nums = [5, -2, 9, -1, 7]
sorted_nums = sorted(nums, key=abs)
print(sorted_nums) # 输出:[-1, -2, 5, 7, 9]
通过 key
参数的使用,我们可以自定义排序规则,从而满足更为复杂的排序需求。
2. key函数的基本用法
key
参数可以接受一个函数作为参数,该函数将在排序中被调用。这个函数的作用是为每个元素提供一个关键字,根据这个关键字进行排序。关键字可以是任意类型的对象。
2.1 排序字符串
首先,我们来看一个最简单的示例,对字符串列表进行排序。我们可以使用 key
参数来指定一个函数,这个函数会将每个字符串转换为其长度,然后按照长度进行排序:
words = ['apple', 'banana', 'orange', 'grape']
sorted_words = sorted(words, key=len)
print(sorted_words) # 输出:['grape', 'apple', 'banana', 'orange']
在这个示例中,我们指定了 key=len
,len
函数将会作用于每个字符串,返回字符串的长度作为关键字进行排序。因此,结果中的字符串按照长度从短到长进行排序。
2.2 排序元组
对于元组列表,我们可以使用 key
参数指定一个函数来排序。例如,按照元组的第二个元素进行排序:
students = [('Alice', 95), ('Bob', 83), ('Cindy', 90), ('David', 88)]
sorted_students = sorted(students, key=lambda x: x[1])
print(sorted_students)
# 输出:[('Bob', 83), ('David', 88), ('Cindy', 90), ('Alice', 95)]
在这个示例中,我们使用了一个匿名函数 lambda x: x[1]
。这个函数接受一个元组作为参数 x
,并返回元组的第二个元素作为关键字进行排序。因此,按照学生的成绩从低到高进行排序。
2.3 排序对象
如果要对自定义的对象进行排序,可以通过定义对象的 __lt__
方法(即“小于”运算符的重载)和使用 key
参数来实现。例如,我们定义了一个 Person
类,其中的 name
和 age
属性将用于排序。我们可以通过在类中定义 __lt__
方法来实现自定义的排序规则:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __lt__(self, other):
return self.age < other.age
people = [Person('Alice', 23), Person('Bob', 19), Person('Cindy', 27)]
sorted_people = sorted(people, key=lambda x: x.age)
for person in sorted_people:
print(person.name, person.age)
# 输出:
# Bob 19
# Alice 23
# Cindy 27
在这个示例中,我们定义了 Person
类,并在类中重载了 __lt__
方法。__lt__
方法用于确定两个对象的大小关系,因此可以被排序函数使用。在排序中,我们使用 key
参数将 age
属性作为关键字进行排序。因此,按照人的年龄从小到大进行排序。
3. 多重排序
有时候,我们需要对多个条件进行排序。在这种情况下,可以使用 key
参数接受一个由多个关键字组成的元组。
3.1 升序和降序
首先,我们来看一下如何对多个条件进行升序和降序排序。
students = [('Alice', 95, 19), ('Bob', 83, 20), ('Cindy', 90, 19), ('David', 88, 20)]
sorted_students = sorted(students, key=lambda x: (x[2], -x[1]))
for student in sorted_students:
print(student)
# 输出:
# ('Alice', 95, 19)
# ('Cindy', 90, 19)
# ('Bob', 83, 20)
# ('David', 88, 20)
在这个示例中,我们使用了一个由多个关键字组成的元组 (x[2], -x[1])
。第一个关键字是年龄 x[2]
,第二个关键字是成绩 -x[1]
。在关键字后加上负号 -
,表示对该关键字进行降序排序。因此,学生首先按照年龄进行升序排序,如果年龄相同,则按照成绩进行降序排序。
3.2 多重排序规则
对于多重排序规则,可以使用任意的函数来为每个关键字提供排序依据。
students = [
{'name': 'Alice', 'age': 19, 'score': 95},
{'name': 'Bob', 'age': 20, 'score': 83},
{'name': 'Cindy', 'age': 19, 'score': 90},
{'name': 'David', 'age': 20, 'score': 88}
]
sorted_students = sorted(students, key=lambda x: (x['age'], -x['score']), reverse=True)
for student in sorted_students:
print(student)
# 输出:
# {'name': 'Bob', 'age': 20, 'score': 83}
# {'name': 'David', 'age': 20, 'score': 88}
# {'name': 'Cindy', 'age': 19, 'score': 90}
# {'name': 'Alice', 'age': 19, 'score': 95}
在这个示例中,我们对学生信息使用字典进行表示,每个学生信息包含姓名、年龄和成绩。我们指定了一个匿名函数作为 key
参数,并使用元组 (x['age'],-x['score'])
来定义排序规则。首先按照年龄进行升序排序,如果年龄相同,则按照成绩进行降序排序。同时,我们将 reverse
参数设为 True
,表示对排序结果进行反转,得到降序排序的结果。
4. 实际应用
在实际应用中,key
排序可以帮助我们处理各种复杂的排序需求。下面我们将介绍两个实际场景的示例。
4.1 按照频次排序
假设我们有一个字符串列表,希望按照每个字符串出现的频次进行排序。可以使用 collections.Counter
来计算频次,并传递给 key
参数进行排序。
from collections import Counter
strings = ['apple', 'banana', 'orange', 'grape', 'apple', 'banana']
counts = Counter(strings)
sorted_strings = sorted(strings, key=lambda x: counts[x], reverse=True)
print(sorted_strings)
# 输出:['apple', 'apple', 'banana', 'banana', 'orange', 'grape']
在这个示例中,我们使用 Counter
对象 counts
统计了每个字符串出现的频次。然后,通过 key
参数传递了一个匿名函数,该函数使用 counts
对象根据每个字符串的频次进行排序,reverse=True
表示按照降序排序。因此,我们得到了按照频次排序的结果。
4.2 对字典列表进行排序
假设我们有一个字典列表,每个字典包含了一个人的姓名和年龄。我们希望先按照年龄从小到大进行排序,年龄相同的情况下按照姓名进行升序排序。
people = [{'name': 'Alice', 'age': 23}, {'name': 'Bob', 'age': 19}, {'name': 'Cindy', 'age': 27}]
sorted_people = sorted(people, key=lambda x: (x['age'], x['name']))
for person in sorted_people:
print(person)
# 输出:
# {'name': 'Bob', 'age': 19}
# {'name': 'Alice', 'age': 23}
# {'name': 'Cindy', 'age': 27}
在这个示例中,我们使用了元组 (x['age'], x['name'])
作为排序的依据。首先按照年龄进行升序排序,如果年龄相同,则按照姓名进行升序排序。因此,我们得到了按照年龄和姓名排序的结果。
结论
通过使用 key
参数进行排序,我们可以灵活地定义排序规则。无论是对字符串、元组还是自定义对象的排序,key
排序都具有很高的适应性和扩展性。通过合理运用 key
排序,我们可以处理各种复杂的排序需求。在实际应用中,掌握 key
排序的技巧将为我们带来更大的便利性和灵活性,提高代码的可读性和可维护性。