Python Sort

Python不仅提供了list.sort()方法来实现列表的排序,而且提供了内建sorted()函数来实现对复杂列表的排序以及按照字典的key和value进行排序。

sorted函数原型

1
2
3
4
sorted(data, cmp=None, key=None, reverse=False)  
#data为数据
#cmp和key均为比较函数
#reverse为排序方向,True为倒序,False为正序

基本用法

对于列表

直接进行排序

1
2
3
4
5
6
7
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]

对于字典

只对key进行排序

1
2
3
4
5
6
7
8
9
sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]
```

### key函数

key函数应该接受一个参数并返回一个用于排序的key值。由于该函数只需要调用一次,因而排序速度较快。

复杂列表

student_tuples = [
(‘john’, ‘A’, 15),
(‘jane’, ‘B’, 12),
(‘dave’, ‘B’, 10),
]
sorted(student_tuples, key=lambda student: student[2]) # sort by age
[(‘dave’, ‘B’, 10), (‘jane’, ‘B’, 12), (‘john’, ‘A’, 15)]

1
2

如果列表内容是类的话,

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),
]
sorted(student_objects, key=lambda student: student.age) # sort by age
[(‘dave’, ‘B’, 10), (‘jane’, ‘B’, 12), (‘john’, ‘A’, 15)]

1
2

字典

student = [ {“name”:”xiaoming”, “score”:60}, {“name”:”daxiong”, “score”:20},
{“name”:”maodou”, “score”:30},
]
student
[{‘score’: 60, ‘name’: ‘xiaoming’}, {‘score’: 20, ‘name’: ‘daxiong’}, {‘score’: 30, ‘name’: ‘maodou’}]
sorted(student, key=lambda d:d[“score”])
[{‘score’: 20, ‘name’: ‘daxiong’}, {‘score’: 30, ‘name’: ‘maodou’}, {‘score’: 60, ‘name’: ‘xiaoming’}]

1
2

此外,Python提供了operator.itemgetter和attrgetter提高执行速度。

from operator import itemgetter, attrgetter
student = [
(“xiaoming”,60),
(“daxiong”, 20),
(“maodou”, 30}]
sorted(student, key=lambda d:d[1])
[(‘daxiong’, 20), (‘maodou’, 30), (‘xiaoming’, 60)]
sorted(student, key=itemgetter(1))
[(‘daxiong’, 20), (‘maodou’, 30), (‘xiaoming’, 60)]

1
2

operator提供了多个字段的复杂排序。

sorted(student, key=itemgetter(0,1)) #根据第一个字段和第二个字段
[(‘daxiong’, 20), (‘maodou’, 30), (‘xiaoming’, 60)]
operator.methodcaller()函数会按照提供的函数来计算排序。

messages = [‘critical!!!’, ‘hurry!’, ‘standby’, ‘immediate!!’]
sorted(messages, key=methodcaller(‘count’, ‘!’))
[‘standby’, ‘hurry!’, ‘immediate!!’, ‘critical!!!’]

1
2
3
4
5
6

首先通过count函数对"!"来计算出现次数,然后按照出现次数进行排序。

### CMP

cmp参数是Python2.4之前使用的排序方法。

def numeric_compare(x, y):
return x - y

sorted([5, 2, 4, 1, 3], cmp=numeric_compare)
[1, 2, 3, 4, 5]
def reverse_numeric(x, y):
return y - x
sorted([5, 2, 4, 1, 3], cmp=reverse_numeric)
[5, 4, 3, 2, 1]
在functools.cmp_to_key函数提供了比较功能

sorted([5, 2, 4, 1, 3], key=cmp_to_key(reverse_numeric))
[5, 4, 3, 2, 1]

def cmp_to_key(mycmp):
‘Convert a cmp= function into a key= function’
class K(object):
def init(self, obj, *args):
self.obj = obj
def lt(self, other):
return mycmp(self.obj, other.obj) < 0
def gt(self, other):
return mycmp(self.obj, other.obj) > 0
def eq(self, other):
return mycmp(self.obj, other.obj) == 0
def le(self, other):
return mycmp(self.obj, other.obj) <= 0
def ge(self, other):
return mycmp(self.obj, other.obj) >= 0
def ne(self, other):
return mycmp(self.obj, other.obj) != 0
return K
`