Python 排序
对python
的list
进行排序,有方法sort
和sorted
其中,sort()
为list
内置的方法,而sorted()
为全局内置的方法
简单的升序排序
-
直接调用
sorted()
方法,它将返回一个新的list
,新的list
元素基于小于运算符(__It__)
来排序a = [1,5,3,2,4] b = sorted(a) print a, b [1, 5, 3, 2, 4] [1, 2, 3, 4, 5]
-
也可以使用
list.sort()
方法排序,此时list
将被修改,一般来讲,不如sorted()
方便,但是如果不需要原来的list
,通常更加高效a = [1,5,3,2,4] a.sort() print a [1, 2, 3, 4, 5]
-
区别:
list.sort()
仅被定义在list
中,而sorted()
方法对所有的可迭代序列都有效,比如字典a = {1:'E', 5:'A', 4:'B', 3:'C', 2:'D'} b = sorted(a) print a, b {1: 'E', 2: 'D', 3: 'C', 4: 'B', 5: 'A'} [1, 2, 3, 4, 5]
注意:字典打印无顺序
key参数/函数
从python2.4
开始,list.sort()
和sorted()
这两个函数增加了key
参数来指定一个函数,此函数将在每个元素比较之前被调用。
例:通过key
指定函数来忽略字符串的大小写
sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
key
参数的值为一个函数,此函数只有一个参数且返回一个值用来进行比较,(lambda
函数本身是可以有多个参数的),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)]
对复杂对象进行排序操作
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)]
Operator模块函数
python提供了一些更加方便的访问方法来实现上面lambda
函数的功能,operator
模块有itemgetter
,attrgetter
,从python2.6开始,还提供了methodcaller
方法,使用这些方法,可以快速决定使用哪个属性进行排序。
itemgetter选择第几个属性,attrgetter选择具体属性的名称,主要用于复杂对象,例子如下:
from operator import itemgetter, attrgetter
sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
使用operator,还可以进行多级排序,例如,先以grade,再以age排序:
sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
升序和降序
list.sort()
和sorted()
都提供了一个reverse(Ture or False)
来表示升序或者降序排序
reverse = Ture
:表示降序
reverse = False
:表示升序
排序稳定性和复杂排序
从python2.2开始,排序被保证是稳定的。
其他方法:
DSU:很古老,不怎么用了
cmp:python2.x中可以使用,python3.x已经摒弃了,可以使用函数cmp_to_key()
进行转换使用
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
从python2.7,cmp_to_key()
函数被增加到了functools模块中
多级排序(将边按照BFS排序)
元组是用来进行多级排序的
c = list(nx.algorithms.coloring.strategy_connected_sequential_bfs(G, 0))
cc = {}
for i in range(len(c)):
cc[c[i]] = i
sortedlist = sorted(edges, key = lambda x: (cc[x[0]], cc[x[1]]))
c
为按照图G
进行bfs
得到的节点集
cc
为节点集中节点的相对顺序,以此为偏序关系
edges
为需要排序的边list
,形式为(src, tar)
在这个例子中,对所有的边进行排序,首先按照边的源节点的相对顺序排序,然后按照边的目标节点的相对顺序排序,lambda
函数的形式如上。
其他
排序内部是调用元素的__cmp__
来进行的,所以我们可以为元素类型增加__cmp__
方法使得元素可以比较,例如:
Student.__lt__ = lambda self, other: self.age < other.age
sorted(student_objects)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
key
函数不仅可以访问需要排序的内部数据,还可以访问外部的资源。例如,如果学生的成绩存储在dictionary
中,则可以根据dictionary
来对学生的名字的list
进行排序,如下:
students = ['dave', 'john', 'jane']
newgrades = {'john': 'F', 'jane':'A', 'dave': 'C'}
sorted(students, key=newgrades.__getitem__)
['jane', 'dave', 'john']