Python中列表中有一个内置方法sort()方法,可以直接对列表进行修改;还有一个sorted()方法,它会从一个可迭代对象构建一个新的列表。
基本排序
简单的升序非常简单,只需调用sorted()方法,直接返回一个新列表
li1 = [3, 1, 8, 39, 4, 89]
li2 = sorted(li1)
print(li2)
# 输出:[1, 3, 4, 8, 39, 89]
也可以直接使用list.sort(),会直接修改列表
li1 = [3, 1, 8, 39, 4, 89]
li1.sort()
# li2 = sorted(li1)
print(li1)
还有一个区别,list.sort()方法只是为列表定义的;而sorted()可以对所有可迭代对象进行排序,但只会返回一个列表
Key关键字
list.sort()和sorted()都有一个形参Key,来指定在进行比较之前要在每个列表元素调用的函数
li = sorted('This is a test string from Wang'.split(), key=str.lower)
print(li)
# 输出:['a', 'from', 'is', 'string', 'test', 'This', 'Wang']
key形参的值应该是一个函数,它接受一个参数并返回一个用于排序的键,这种技巧很快,因为对于每个输入记录只会调用一次key函数。
一种常见的操作是使用对象的一些索引作为键对复杂对象进行排序
student_tuple = [
('john', 'S', '16'),
('tom', '2S', '20'),
('jemmy', 'SB', '18'),
('ming', 'SS', '13')
]
print(sorted(student_tuple, key=lambda student: student[2]))
# 输出:[('ming', 'SS', '13'), ('john', 'S', '16'), ('jemmy', 'SB', '18'), ('tom', '2S', '20')]
字典排序
student_info = {
'Tom': ['male', '15', 'A'],
'Jim': ['female', '17', 'A+'],
'Alice': ['male', '20', 'B+']
}
print(sorted(student_info.items(), key=lambda x: x[1][1])) # 按照字典值的第二个元素排序
# x相当于字典遍历出来的一个键值元祖
student_info = [
{'name':'tom', 'age': '15', 'grade':'A'},
{'name':'Jim', 'age': '17', 'grade':'A++'},
{'name':'Alice', 'age': '20', 'grade':'B+'},
]
print(sorted(student_info, key=lambda key: key['age']))
同样适用于具有命名属性的对象
class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age
def __repr__(self):
return repr((self.name, self.grade, self.age))
student_tuple = [
Student('john', 'A', '14'),
Student('tom', 'B', '20'),
Student('jemmy', 'B+', '18'),
Student('ming', 'B-', '16')
]
print(sorted(student_tuple, key=lambda x:x.age))
# 输出:[('john', 'A', '14'), ('ming', 'B-', '16'), ('jemmy', 'B+', '18'), ('tom', 'B', '20')]
Operator模块函数
operator函数包含itemgetter()和attrgetter(),使用这些函数上述例子会更加简单
from operator import itemgetter
student_tuple = [
('john', 'S', '16'),
('tom', '2S', '20'),
('jemmy', 'SB', '18'),
('ming', 'SS', '13')
]
print(sorted(student_tuple, key=itemgetter(2)))
student_tuple = [
Student('john', 'A', '16'),
Student('tom', 'B', '20'),
Student('jemmy', 'B+', '18'),
Student('ming', 'B-', '16')
]
print(sorted(student_tuple, key=attrgetter('age')))
operator模块还允许多级排序,例如按照年龄排序,然后按照名字排序
from operator import itemgetter
student_tuple = [
('john', 'S', '16'),
('tom', '2S', '20'),
('jemmy', 'SB', '18'),
('ming', 'SS', '16')
]
print(sorted(student_tuple, key=itemgetter(2, 0)))
# 输出:[('john', 'S', '16'), ('ming', 'SS', '16'), ('jemmy', 'SB', '18'), ('tom', '2S', '20')]
升序和降序
list.sort()和sorted()接受布尔值reverse参数,用于标记升序降序;reverse为True降序,False升序
排序的稳定性和排序复杂度
排序稳定性指多个元素具有相同的键值时,将保留原来的顺序
data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
print(sorted(data, key=itemgetter(0)))
# 输出:[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]
这样就可以允许我们进行一系列排序步骤中构建复杂的排序,例如:要先按照age降序,然后在按照名字升序