在Python中,针对排序问题提供了内置函数sorted()及列表的内置方法List.sort()
1 sorted()函数
调用格式为
sorted
(iterable, *, key=None, reverse=False)#其中key:声明iterable中每个元素用于比较的键。缺省时默认值为None,直接比较元素
#reverse为一个布尔值,默认为False,此时为升序排序。当设为True时,列表元素按降序进行比较排序
#输出为列表数据类型
1.1 示例
1、对字典类型进行默认排序
>>> sorted({"中国":"北京","美国":"华盛顿","法国":"巴黎"})
['中国', '法国', '美国']>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]2、对列表进行排序
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]3、对集合类型进行排序
>>> sorted({1,2,36,35,5})
[1, 2, 5, 35, 36]
1.2 关键函数(Key Functions)
sorted()函数除了上述中的默认排序以外,可以通过对Key进行设置人为定义排序优先级。有点类似于给每个元素中属性分配优先级权重。
key 形参的值应该是一个函数,它接受一个参数并并返回一个用于排序的键。这种技巧速度很快,因为对于每个输入记录只会调用一次 key 函数,所以我们能看到不同的key键值函数
例如,下面是一个不区分大小写的字符串比较:
给定字符串"This is a test string from Ruliu"
1、key缺省情况下排序
>>> sorted("This is a test string from Ruliu".split())
['Ruliu', 'This', 'a', 'from', 'is', 'string', 'test']2、key=str.lower
>>> sorted("This is a test string from Ruliu".split(),key=str.lower)
['a', 'from', 'is', 'Ruliu', 'string', 'test', 'This']3、reverse=True
>>> sorted("This is a test string from Ruliu".split(),key=str.lower,reverse=True)
['This', 'test', 'string', 'Ruliu', 'is', 'from', 'a']
对于排序对象为元组或者字典类型时,这时候通常会引入python中的lambda函数用于构建键值函数。
lambda函数
lambda函数性质
- lambda函数是一种匿名函数,即没有名字的函数
- 通过使用lambda保留字进行函数定义,函数名是返回的结果
- lambda函数用于定义简单的、能够在一行内表示的函数------这也就是为什么关键函数要用lambda定义的原因
lambda函数定义形式:func=lambda 参数:函数描述
f=lambda x,y:x+y 即f(x,y)=x+y
所以,可以通过选择对象的一些索引作为键对复杂对象进行排序。例如
>>> student_tuples = [('john', 'A', 15),('jane', 'B', 12),('dave', 'B', 10)]
>>> sorted(student_tuples, key=lambda student: student[2]) #以年龄为排序标准,默认reverse=False即增序
[('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))
>>> sorted(student_objects, key=lambda student: student.age)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
1.3 Operator模块函数
为了使访问器功能更加容易,Python的operator模块提供了itemgetter()、attrgetter()函数用于获取元组类型及具有命名属性对象的属性。
对于元组类型
>>> from operator import itemgetter,attrgetter
>>> student_tuples = [('john', 'A', 15),('jane', 'B', 12),('dave', 'B', 10)]
>>> sorted(student_tuples, key=itemgetter(2)) #选用元组中的第三个item作为排序键
[('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=attrgetter('age')) #选用age属性进行排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]>>> sorted(student_objects, key=attrgetter('grade')) #选用grade进行排序
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]>>> sorted(student_objects, key=attrgetter('grade', 'age')) #先按grade排序,在grade相同情况下参考age排序
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
1.4 sorted()排序的升序和降序
对于sorted
(iterable, *, key=None, reverse=False) 函数,在调用时key,reverse可以缺省。已经讲完key的作用。reverse的作用很简单。当调用sorted()函数而又不设置reverse为True时。默认为升序。当我们想要得到降序排列结果时,只需要reverse=True即可。如下
>>> sorted(student_objects, key=lambda student: student.age)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
>>> sorted(student_objects, key=lambda student: student.age,reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
2 list.sort()
list.sort()作为列表的内置方法,调用格式为list.sort(*,key=None,reverse=False) 可以通过设置键值函数key及reverse选择排序方法及增降排序形式。与上文sorted()提到的差不多。
区别
list.sort()方法只能接受列表类型数据,当对字典类型或者其他非列表类型进行list.sort()排序时。需要转换为list进而进行排序。而sorted()函数可以接受任何迭代对象
应用
#CalHamletV1.py
def getText():
txt=open("hamlet.txt","r").read()
txt=txt.lower()
for ch in '!"#$%&()*+,-./:;<=>?@[\\]^_{|}~''':
txt=txt.replace(ch," ") #归一化处理结果
return txt
hamletTxt=getText()
words=hamletTxt.split()
counts={}
for word in words:
counts[word]=counts.get(word,0)+1
items=list(counts.items()) #返回字典d中所有的键值对信息
items.sort(key=lambda x:x[1],reverse=True) #设置键值函数,选择字典类型的值按从大到小排序。即高频到低频
for i in range(10):
word,count=items[i]
print("{0:<10}{1:>5}".format(word,count))
结果:PS:直接偷的