sort()和sorted()
- L.sort():该函数第一个参数iterable为任意可以迭代的对象,cmp是比较函数,通常为lambda函数,key是用于比较的关键字,reverse表示排序结果是否反转,需要特别注意的是,该函数只适用于列表,而非任意可以迭代的对象。cmp是比较函数,接受两个对象参数 x 和 y,返回 负数(x<y),0(x=y),正数(x>y)
- sorted():该函数第一个参数iterable为任意可以迭代的对象,cmp是比较函数,通常为lambda函数,key是用于比较的关键字,reverse表示排序结果是否反转。
A = [3,6,1,5,4,2]
A.sort() // [1, 2, 3, 4, 5, 6]
student = [['Tom', 'A', 20], ['Jack', 'C', 18], ['Andy', 'B', 11]]
student.sort(key=lambda student: student[2])
学生列表中包含列表,每个列表是学生的姓名、成绩以及年龄,排序过程中指定了key为学生的年龄,所以排序的结果为:
[['Andy', 'B', 11], ['Jack', 'C', 18], ['Tom', 'A', 20]]
通过定义 key 和 cmp 都可以完成排序,但是这两者之间有什么区别呢?cmp传入的函数在整个排序过程中会调用多次,因为会进行多次比较,所以函数调用开销较大,因此使用 key 的效率比 cmp 的效率要高。
B = 'Python'
sorted(B)
C = (3, 6, 1, 5, 4, 2)
sorted(C)
D = [3, 6, 1, 5, 4, 2]
sorted(D)
E = {'1': 'a', '2': 'b', '0': 'c'}
sorted(E.items())
需要注意的是,该函数会返回一个排序后的列表,原有可迭代对象保持不变,这与 L.sort() 函数不同。然而,这会浪费较大的存储空间,尤其是数据量较大时。所以,在列表进行排序时,需要考虑是否需要保存原列表,如果无需保存原列表,则优先使用L.sort() 节省内存空间,提高效率。
有的排序可能需要根据两个关键字,常用的比如单词的排序,第一个字母相同然后根据第二个字母排序,Python中的 sorted() 函数是否支持这种实现呢?答案是肯定的,再设置 key 时指定多个属性即可:
L = ['cat', 'binary', 'big', 'dog']
print sorted(L, key=lambda x: (x[0], x[1], x[2]))
['big', 'binary', 'cat', 'dog']
按关键词排序
在list.sort()和sorted中,都可以根据指定的key值排序。例如:
>>> qw="I am Qiwsir you can read my articles im my blog".split()
>>> qw
['I', 'am', 'Qiwsir', 'you', 'can', 'read', 'my', 'articles', 'im', 'my', 'blog']
>>> sorted(qw,key=str.lower) #按照字母升序排列
['am', 'articles', 'blog', 'can', 'I', 'im', 'my', 'my', 'Qiwsir', 'read', 'you']
>>> qw
['I', 'am', 'Qiwsir', 'you', 'can', 'read', 'my', 'articles', 'im', 'my', 'blog']
>>> qw.sort(key=str.lower)
>>> qw
['am', 'articles', 'blog', 'can', 'I', 'im', 'my', 'my', 'Qiwsir', 'read', 'you']
此外,key还可以接收函数的单一返回值,按照该值排序。例如:
>>> name_mark_age = [('zhangsan','A',15),('LISI','B',14),('WANGWU','A',16)]
>>> sorted(name_mark_age, key = lambda x: x[2]) #根据年龄排序
[('LISI', 'B', 14), ('zhangsan', 'A', 15), ('WANGWU', 'A', 16)]
>>> sorted(name_mark_age, key = lambda x: x[1]) #根据等级排序
[('zhangsan', 'A', 15), ('WANGWU', 'A', 16), ('LISI', 'B', 14)]
>>> sorted(name_mark_age, key = lambda x: x[0]) #根据姓名排序
[('LISI', 'B', 14), ('WANGWU', 'A', 16), ('zhangsan', 'A', 15)]
除了上述方式,python中还提供了一个选择循环选择指定元组值的模块
>>> from operator import itemgetter #官方文档:https://docs.python.org/2/library/operator.html#module-operator
>>> name_mark_age.append(('zhaoliu','B',16))
>>> name_mark_age
[('zhangsan', 'A', 15), ('LISI', 'B', 14), ('WANGWU', 'A', 16), ('zhaoliu', 'B', 16)]
>>> sorted(name_mark_age,key=itemgetter(2)) #按照年龄排序
[('LISI', 'B', 14), ('zhangsan', 'A', 15), ('WANGWU', 'A', 16), ('zhaoliu', 'B', 16)]
>>> sorted(name_mark_age,key=itemgetter(1,2)) #先按照等级排序,相同等级看年龄
[('zhangsan', 'A', 15), ('WANGWU', 'A', 16), ('LISI', 'B', 14), ('zhaoliu', 'B', 16)]
在官方文档上,有这样一个例子,和上面的操作是完全一样的。
>>> 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_objects = [
Student('john', 'A', 15), #注意这里,用class Student来生成列表内的值
Student('jane', 'B', 12), #因此,可以通过student_objects[i].age来访问某个名称的年龄,i=0,则是john的年龄
Student('dave', 'B', 10),
]
>>> sorted(student_objects, key=lambda student: student.age)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
也可以引用operator模块来实现上述排序
>>>from operator import attrgetter
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
**总结:**sorted的能力超强,不仅实现排序,还能按照指定关键词排序。
以上例子都是升序,如果,增加reverse=True。例如:
>>>from operator import itemgetter
>>> name_mark_age
[('zhangsan', 'A', 15), ('LISI', 'B', 14), ('WANGWU', 'A', 16), ('zhaoliu', 'B', 16)]
>>> sorted(name_mark_age, key=itemgetter(2),reverse=True)
[('WANGWU', 'A', 16), ('zhaoliu', 'B', 16), ('zhangsan', 'A', 15), ('LISI', 'B', 14)]
总结
- L.sort() 函数只适用于列表排序,而sorted()函数适用于任意可以迭代的对象排序。
- L.sort() 函数排序会改变原有的待排序列表,而sorted()函数则不会改变。所以在使用列表进行排序时,需要考虑是否需要保存原列表,如果无需保存原列表,则优先使用L.sort() 节省内存空间,提高效率。
- 两个函数通过定义 key 和 cmp 都可以完成排序,但是 key 的效率要远远高于 cmp,所以要优先使用 key 。