Python中的排序
来源:互联网 发布:数据迁移工程师 编辑:程序博客网 时间:2024/05/29 18:29
这篇博客介绍了Python(3.3)中的序列数据类型和对象的排序,在原文基础上有所修改。
原文链接:http://docs.python.org/3/howto/sorting.html
基本排序:
Python中的列表(list)有两个内建排序函数
1.list.sort(),这会替换原列表:
sort(*, key=None, reverse=None)
2.sorted()函数会接受一个可迭代序列,返回一个新列表,注意是列表(序列进去,列表出来):
sorted(iterable[, key][, reverse])
下面是一个升序排序的简单例子:
>>> 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]
List.sort()只能在列表上使用,而sorted()可在任何可迭代序列上使用:
>>> sorted({1: ’D’, 2: ’B’, 3: ’B’, 4: ’E’, 5: ’A’})[1, 2, 3, 4, 5]
接受参数的排序:
同C++和其他高级语言一样,Python同样接受排序参数来使排序函数按照特定的比较规则进行排序。
>>> sorted("This is a test string from Andrew".split(), key=str.lower)[’a’, ’Andrew’, ’from’, ’is’, ’string’, ’test’, ’This’]>>> sorted("This is a test string from Andrew".split())[’Andrew’,’This’,’a’, ’from’, ’is’, ’string’, ’test’, ]
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)]>>> 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 模块中的函数作为key:
Operator模块中的itemgetter(), attrgetter(), 和methodcaller()可以更快速便捷的获得对象属性。
例如我们想按照年龄来进行排序:
>>> 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)]
我们也可以先按成绩,后按年龄来排序:
>>> 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)]
升序与降序:
除了key参数以外,sorted与sort函数同样接受reverse参数,reverse参数是一个布尔值,True和False分别对应升序与降序:
>>> sorted(student_tuples, key=itemgetter(2), reverse=True)[(’john’, ’A’, 15), (’jane’, ’B’, 12), (’dave’, ’B’, 10)]>>> sorted(student_objects, key=attrgetter(’age’), reverse=True)[(’john’, ’A’, 15), (’jane’, ’B’, 12), (’dave’, ’B’, 10)]
顺序稳定性与复杂排序:
在一次排序中,排序函数只会改变需要改变的对象位置,例如我们按照年龄排序,当存在两个相同年龄的人时,排序函数不会改变这两个人在原序列中的顺序。
>>> data = [(’red’, 1), (’blue’, 1), (’red’, 2), (’blue’, 2)]>>> sorted(data, key=itemgetter(0))[(’blue’, 1), (’blue’, 2), (’red’, 1), (’red’, 2)]
这一属性允许我们在序列中使用一系列的步骤进行排序,而不会出现逻辑问题。例如我们想在student对象中按成绩降序排列,且按年龄升序排列。
>>> s = sorted(student_objects, key=attrgetter(’age’))# sort on secondary key>>> sorted(s, key=attrgetter(’grade’), reverse=True)# then sort on primary key, descending[(’dave’, ’B’, 10), (’jane’, ’B’, 12), (’john’, ’A’, 15)]
在Python中使用的是Timsort排序算法,这使python的复杂排序效率非常之高。
2.X版本中的DSU排序:
DSU( Decorate-Sort-Undecorate)排序包含三个步骤:
1.为要排序的列表添加一个新值--决定列表顺序的值,这个新的列表称为Decorated-List(Decorate)。
2.排序(sort)。
3.还原拥有了新顺序的原列表,即删除掉1中创建的顺序控制值(Undecorate)。
>>> decorated = [(student.grade, i, student) for i, student in enumerate(student_objects)]>>> decorated.sort()>>> [student for grade, i, student in decorated] # undecorate[(’john’, ’A’, 15), (’jane’, ’B’, 12), (’dave’, ’B’, 10)]
包含进索引i并不是必需的,但包含i有这么两点好处:
1.顺序稳定性。元组按照字典序(先第一个比,若相同第二个比)比较,包含进i可使在grade相同的情况下,保持住原列表中的顺序。
2.防止元列表对象无法进行比较。包含i使得decorated-list最多只可比较两个元素,第三个元素(例中的student)比较不到。当第三个元素是不可比较的(如复数),这可拯救一次错误的排序,使得列表得以有稳定顺序。
DSU在perl编程中称作 Schwartzian transform,在python中,当我们拥有了key参数后,这个技巧已经不是必需的了。
2.X版本中的cmp参数:
在3.0以后的版本中,cmp参数被彻底移除。
在Python2.X版本中,我们可以写出一个cmp函数,并将其传入sort函数,像这样:
>>> def numeric_compare(x, y):return x - y>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare)[1, 2, 3, 4, 5]#Or you can reverse the order of comparison with:>>> def reverse_numeric(x, y):return y - x>>> sorted([5, 2, 4, 1, 3], cmp=reverse_numeric)[5, 4, 3, 2, 1]
在3.X中,虽然不再提供cmp,但我们可以使用标准库functools的 functools.cmp_to_key()函数来转换cmp函数:
>>> sorted([5, 2, 4, 1, 3], key=functools.cmp_to_key(reverse_numeric))[5, 4, 3, 2, 1]
Cmp_to_key的函数实现类似于这样:
def cmp_to_key(mycmp): ’Convert a cmp= function into a key= function’ class K: 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
其他与结束:
1.对象间的比较:在Python中,对象间的比较默认使用__it__()方法。所以我们可以为对象创建__it__()方法来为其定义顺序。
>>> Student.__lt__ = lambda self, other: self.age < other.age>>> sorted(student_objects)[(’dave’, ’B’, 10), (’jane’, ’B’, 12), (’john’, ’A’, 15)]
2.key的函数不仅仅局限于要排序的序列内,它可以扩展到一个外部序列,当然这个外部序列需要匹配需要排序的键值。
>>> students = [’dave’, ’john’, ’jane’]>>> newgrades = {’john’: ’F’, ’jane’:’A’, ’dave’: ’C’}>>> sorted(students, key=newgrades.__getitem__)[’jane’, ’dave’, ’john’]
在The Art of Computer Programming这本书中,作者指出计算机有25%的时间在进行排序操作。我们不知道这个数字是否准确,但排序的确是计算机科学中极为重要的一部分。
- Python中的排序
- python中的归并排序
- Python中的排序
- python中的字典排序!
- python 字典中的排序
- python中的排序
- Python中的字典排序
- Python 中的排序
- python中的排序
- python 中的排序大法
- Python中的排序
- python中的排序
- python中的排序和numpy中的排序
- python中的列表排序操作
- Python中的对象的排序
- Python 中的列表排序函数
- 【Python】Python_learning2:python中的冒泡排序
- Python(8) python中的冒泡排序、快速排序
- STL初涉~
- ajax的原理
- HDU 4544 湫湫系列故事——消灭兔子
- android的多屏支持
- 内核分析PE获取DLL导出函数地址
- Python中的排序
- Android LCD调试实例流程
- POJ 2752 Seek the Name, Seek the Fame
- VIM命令
- Android TextView文字超出一屏不能显示其它的文字 解决方案
- The server does not support version 3.0 of the J2EE Web module specification
- hdu2572
- HttpStatus
- Const,Const函数,Const变量,函数后面的Const 总结