Skip to content

Commit 68f1af0

Browse files
committed
python的sorted排序分析
1 parent 42f02f1 commit 68f1af0

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

Diff for: pics/timsort1.png

16.5 KB
Loading

Diff for: pics/timsort2.png

8.87 KB
Loading

Diff for: python_sort.md

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#python的排序详解
2+
3+
排序,在编程中经常遇到的算法,我也在几篇文章中介绍了一些关于排序的算法。有的高级语言内置了一些排序函数。本文讲述Python在这方面的工作。供使用python的程序员们参考,也让没有使用python的朋友了解python。领略一番“生命有限,请用Python”的含义。
4+
5+
##内置函数sorted()/list.sort()的使用
6+
7+
###简单应用
8+
9+
python对list有一个内置函数:sorted(),专门用于排序。举例:
10+
11+
>>> a=[5,3,6,1,9,2]
12+
>>> sorted(a) #a经过sorted之后,得到一个排序结果
13+
[1, 2, 3, 5, 6, 9] #但是,原有的a并没有受到影响
14+
>>> a
15+
[5, 3, 6, 1, 9, 2]
16+
17+
也可以使用list.sort()来进行上述操作。
18+
19+
>>> a.sort()
20+
>>> a #注意这里,经过list.sort()之后,原有
21+
[1, 2, 3, 5, 6, 9] #a的顺序已经发生变化,与上述不同之处。
22+
23+
**sorted和list.sort()的区别:**list.sort()只能对list类型进行排序。如下:
24+
25+
>>> b_dict={1:'e',3:'m',9:'a',5:'e'}
26+
>>> b_dict.sort()
27+
Traceback (most recent call last):
28+
File "<stdin>", line 1, in <module>
29+
AttributeError: 'dict' object has no attribute 'sort'
30+
31+
而sorted则不然,看例子:
32+
33+
>>> b_dict
34+
{1: 'e', 3: 'm', 5: 'e', 9: 'a'}
35+
>>> sorted(b_dict)
36+
[1, 3, 5, 9]
37+
38+
sorted之后,上述对dictinoary中,将key值取出并排序,返回list类型的排序结果。
39+
40+
###按照指定关键词排序
41+
42+
在list.sort()和sorted中,都可以根据指定的key值排序。例如:
43+
44+
sorted的例子:
45+
46+
>>> qw="I am Qiwsir you can read my articles im my blog".split()
47+
>>> qw
48+
['I', 'am', 'Qiwsir', 'you', 'can', 'read', 'my', 'articles', 'im', 'my', 'blog']
49+
>>> sorted(qw,key=str.lower) #按照字母升序排列
50+
['am', 'articles', 'blog', 'can', 'I', 'im', 'my', 'my', 'Qiwsir', 'read', 'you']
51+
52+
list.sort()的例子:
53+
54+
>>> qw
55+
['I', 'am', 'Qiwsir', 'you', 'can', 'read', 'my', 'articles', 'im', 'my', 'blog']
56+
>>> qw.sort(key=str.lower)
57+
>>> qw
58+
['am', 'articles', 'blog', 'can', 'I', 'im', 'my', 'my', 'Qiwsir', 'read', 'you']
59+
60+
此外,key还可以接收函数的单一返回值,按照该值排序。例如:
61+
62+
>>> name_mark_age = [('zhangsan','A',15),('LISI','B',14),('WANGWU','A',16)]
63+
>>> sorted(name_mark_age, key = lambda x: x[2]) #根据年龄排序
64+
[('LISI', 'B', 14), ('zhangsan', 'A', 15), ('WANGWU', 'A', 16)]
65+
66+
>>> sorted(name_mark_age, key = lambda x: x[1]) #根据等级排序
67+
[('zhangsan', 'A', 15), ('WANGWU', 'A', 16), ('LISI', 'B', 14)]
68+
69+
>>> sorted(name_mark_age, key = lambda x: x[0]) #根据姓名排序
70+
[('LISI', 'B', 14), ('WANGWU', 'A', 16), ('zhangsan', 'A', 15)]
71+
72+
除了上述方式,python中还提供了一个选择循环选择指定元组值的模块
73+
74+
>>> from operator import itemgetter #官方文档:https://docs.python.org/2/library/operator.html#module-operator
75+
>>> name_mark_age.append(('zhaoliu','B',16))
76+
>>> name_mark_age
77+
[('zhangsan', 'A', 15), ('LISI', 'B', 14), ('WANGWU', 'A', 16), ('zhaoliu', 'B', 16)]
78+
79+
>>> sorted(name_mark_age,key=itemgetter(2)) #按照年龄排序
80+
[('LISI', 'B', 14), ('zhangsan', 'A', 15), ('WANGWU', 'A', 16), ('zhaoliu', 'B', 16)]
81+
82+
>>> sorted(name_mark_age,key=itemgetter(1,2)) #先按照等级排序,相同等级看年龄
83+
[('zhangsan', 'A', 15), ('WANGWU', 'A', 16), ('LISI', 'B', 14), ('zhaoliu', 'B', 16)]
84+
85+
86+
在官方文档上,有这样一个例子,和上面的操作是完全一样的。
87+
88+
>>> class Student:
89+
def __init__(self, name, grade, age):
90+
self.name = name
91+
self.grade = grade
92+
self.age = age
93+
94+
def __repr__(self):
95+
return repr((self.name, self.grade, self.age))
96+
97+
>>> student_objects = [
98+
Student('john', 'A', 15), #注意这里,用class Student来生成列表内的值
99+
Student('jane', 'B', 12), #因此,可以通过student_objects[i].age来访问某个名称的年龄,i=0,则是john的年龄
100+
Student('dave', 'B', 10),
101+
]
102+
103+
>>> sorted(student_objects, key=lambda student: student.age)
104+
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
105+
106+
也可以引用operator模块来实现上述排序
107+
108+
>>>from operator import attrgetter
109+
>>> sorted(student_objects, key=attrgetter('age'))
110+
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
111+
>>> sorted(student_objects, key=attrgetter('grade', 'age'))
112+
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
113+
114+
**总结:**sorted的能力超强,不仅实现排序,还能按照指定关键词排序。
115+
116+
以上例子都是升序,如果,增加reverse=True。例如:
117+
118+
>>>from operator import itemgetter
119+
>>> name_mark_age
120+
[('zhangsan', 'A', 15), ('LISI', 'B', 14), ('WANGWU', 'A', 16), ('zhaoliu', 'B', 16)]
121+
>>> sorted(name_mark_age, key=itemgetter(2),reverse=True)
122+
[('WANGWU', 'A', 16), ('zhaoliu', 'B', 16), ('zhangsan', 'A', 15), ('LISI', 'B', 14)]
123+
124+
##sorted的算法
125+
126+
python中的sorted算法,网上有人撰文,说比较低级。其实不然,通过阅读官方文档,发现python中的sorted排序,真的是高大上,用的Timsort算法。什么是Timsort,请看 wiki的解释:http://en.wikipedia.org/wiki/Timsort,另外,国内有一个文档,适当翻译:http://blog.csdn.net/yangzhongblog/article/details/8184707,这里截取一个不同排序算法比较的图示,就明白sorted的威力了。
127+
128+
从时间复杂度来看,Timsort是威武的。
129+
130+
![](./pics/timsort1.png)
131+
132+
从空间复杂度来讲,需要的开销在数量大的时候会增大。
133+
134+
![](./pics/timsort2.png)
135+
136+
综上,可以看出,就一般情况,使用sorted足以能够完成排序的要求,并且是稳定的。
137+
138+
当然,python中也有其它一些排序模块,都可以直接拿过来使用。
139+
140+
本文作者在博客和github上都有多种关于python排序方法和模块的文章说明。

0 commit comments

Comments
 (0)