python中的几个常用高阶函数包括:filter、map、reduce、zip、sorted
本文主要对sorted进行说明
sorted
(iterable, *, key=None, reverse=False)
sorted函数对可迭代的对象进行排序操作,返回新的排序后的列表
示例1 sorted函数和list中的sort方法的区别
alist = [1,4,3,4]
atuple = ('a', 'z', 'Q', 'q', 'Z')
astring = 'treqqwsad'
adict = {1: 'a', 2: 'b'}
aset = {23,542,74,234,534}
print(sorted(alist))
print(sorted(atuple))
print(sorted(adict))
print(sorted(astring))
print(sorted(aset))
b = sorted(alist)
print(b)
print('sorted作用后的alist', alist)
print(alist)
b = alist.sort()
print(b)
print('sort作用后的alist', alist)
#输出
[1, 3, 4, 4]
['Q', 'Z', 'a', 'q', 'z']
[1, 2]
['a', 'd', 'e', 'q', 'q', 'r', 's', 't', 'w']
[23, 74, 234, 534, 542]
[1, 3, 4, 4]
sorted作用后的alist [1, 4, 3, 4]
[1, 4, 3, 4]
None
sort作用后的alist [1, 3, 4, 4]
可见两者的主要区别有两个:
1.作用范围不同。list.sort方法只能作用于list,而sorted函数可以作用于所有可迭代对象,包括字符串、列表、元组、字典、集合。(需要注意一下可迭代对象和序列的范围并不相同:序列主要是指有序的东西,像字符串、列表、元组等都可以通过下标对元素进行访问。而可迭代对象指的内部实现了__iter__方法的数据类型,像字符串、列表、元组、字典、集合都是可迭代对象。可迭代对象包含序列,或者说序列是可迭代对象的一种。)
2.作用结果不同。list.sort作用于列表后,是对列表进行原地排序,返回值是none。所以用b变量试图接收返回值时打印出了none,而再打印列表alist本身时,发现它已经是经过排序后的列表。即列表本身发生了变化。而sorted作用于可迭代对象后,并不是原地排序,而是生成新的排序后的列表。所以用b变量可以接收到新列表,而alist本身并没有变化。
另外上述示例,没有指定key关键字,所以所有排序都是直接比较元素。数字按值大小排序,而字母按ASCII码排序。
示例2 key关键字的使用
print(sorted("This is a test string from Andrew".split(), key=str.lower))
#输出
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
key关键字会依次作用于所有元素,上例中将所有字母先转换为小写进行比较,然后将列表元素进行排序
student_tuples = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
print(sorted(student_tuples, key=lambda student: student[2]))
#输出
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
对于多维可迭代对象的排序,可以用key指定更复杂的表达式用于选择排序条件。上例中按照元组中的第三个元素年龄进行排序
import operator
student_tuples = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
print(sorted(student_tuples, key=operator.itemgetter(2)))
print(sorted(student_tuples, key=operator.itemgetter(1,2)))
print(sorted(student_tuples, key=operator.itemgetter(2,1)))
#输出
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
operator模块提供了多维可迭代对象条件选择更方便的方法itemgetter,可以通过下标直接选择作为排序条件的元素列,同时也可以指定多个排序条件,按照指定顺序依次进行排序,类似mysql的联合索引排序方式。
import operator
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), Student('jane', 'B', 12), Student('dave', 'B', 10)]
print(sorted(student_objects, key=lambda student: student.age))
print(sorted(student_objects, key=operator.attrgetter('age')))
print(sorted(student_objects, key=operator.attrgetter('grade', 'age')))
#输出
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
用样openator也提供了直接按照对象属性为条件排序的方法attrgetter。
示例3 升序和降序排列
alist = [-1, -22, 0, 21, 6, -8]
print(sorted(alist, key=abs))
print(sorted(alist, key=abs, reverse=True))
#输出
[0, -1, 6, -8, 21, -22]
[-22, 21, -8, 6, -1, 0]
reverse参数用于控制升序或降序排列,默认值False为升序排序,当显式指定reverse=True时,为降序排列