细说python3中sort和sorted

sort和sorted的区别
虽然python3中的sort()和sorted()都可以用来排序,但两者之间有以下两个主要区别:
sort只能应用于列表list,sorted可以对所有可迭代对象进行排序
sort方法将直接在原始列表上进行排序,而不会创建新的列表。sorted方法不会改变原始数据,排序后的结果是新生成的。如果我们不需要原始数据,而且数据是列表类型,我们可以使用sort方法来节省空间。否则,使用sorted方法。
sort
sort方法在python2中可以有三个参数:key、cmp和reverse。然而,cmp参数在python3中被取消,只有两个可选参数:key和reverse。参数reverse指定的排序是正的还是倒的,默认是正的FALSE,不多说。参数key指定了一种只包含一个参数的方法,用于从列表中的每个元素中提取比较键。请参见以下例子:
1.通过对元素长度进行排序
strlist=["bbb","ccc","bac","ab","ba"] strlist.sort(key=len) print(strlist)
打印结果如下:
['ab','ba','bbb','ccc','bac']
2.通过元素的字符顺序
strlist=["bbb","BBB","bAc","ab","bac"] strlist.sort()print(strlist) strlist.sort(key=str.lower)print(strlist)
打印结果如下:
['BBB','ab','bAc','bac','bbb'] ['ab','bAc','bac','BBB','bbb']
3.更复杂的排序:列表中的元素是通过字典的属性值进行排序的字典。以下是学生的年龄排名
student=[{"name":"小C","age":12,"score":90},
{"name":"小D","age":13,"score":84},
{"name":"小A","age":14,"score":85},
{"name":"小E","age":15,"score":89},
{"name":"小F","age":12,"score":88}]
student.sort(key=lambdaa:a["age"])
print(student)打印结果如下(换行由我自己处理):
[{'name':'小C','age':12,'score':90},
{'name':'小F','age':12,'score':88},
{'name':'小D','age':13,'score':84},
{'name':'小A','age':14,'score':85},
{'name':'小E','age':15,'score':89}]那么,有些功能无法实现原始cmp参数吗?当然,cmp__可以从functools库中引入to_key来解决这个问题,看看下面的例子:
1.数组倒序
fromfunctoolsimportcmp_to_key list=[5,4,3,2,1] list.sort(key=cmp_to_key(lambdaa,b:b-a)) print(list)
打印结果如下:
[5,4,3,2,1]
2.将数组排成最小数里python的解决方案可以通过以下方式回答(注意倒数第三行,将map类型转换为list类型):
fromfunctoolsimportcmp_to_key classSolution: defPrintMinNumber(self,numbers): numbers=list(map(str,numbers)) numbers.sort(key=cmp_to_key(lambdas1,s2:int(s1+s2)-int(s2+s1) return"".join(numbers)
因为sort只能用list类型,所以sorted方法更为常用。以下是sorted方法
sorted
所有可以迭代的物体都可以用sorted进行排序,排序不会改变原来的物体。sorted接收三个参数:
sorted(iterable,*,key=None,reverse=False)
iterable是可迭代的对象,key和reverse和sort是一样的。看下面的小例子:
student_tuples=[('john','A',15),
('jane','B',12),
('dave','B',10)]
new_tuples=sorted(student_tuples,key=lambdastudent:student[2])
print(student_tuples)
print(new_tuples)打印结果如下:
[('john','A',15),('jane','B',12),('dave','B',10)]
[('dave','B',10),('jane','B',12),('john','A',15)]从打印结果可以看出,新列表是按年龄排序的,原始数据没有改变
由于这种含有key参数的方法非常普遍,python提供了一些方法,使访问器函数更加方便。例如,operator模块中的itemgeter(), attrgetter()方法。
看下面的例子:
fromoperatorimportitemgetter,attrgetter
classStudent:
def__init__(self,name,grade,age):
self.name=name
self.grade=grade
self.age=age
student_objects=[Student('john','A',15),
Student('jane','B',12),
Student('dave','B',10)]
student_tuples=[('john','A',15),
('jane','B',12),
('dave','B',10)]
result1=sorted(student_tuples,key=itemgetter(2)#通过元素的第三个值进行排序
result2=sorted(student_objects,key=attrgetter('age'))#通过对象的age属性进行排序
result3=sorted(student_tuples,key=itemgetter(1,2)#首先通过元素的第一值排序,然后通过第二值排序
result4=sorted(student_objects,key=attrgetter('grade','age'))#通过对象的grade属性排序,然后通过age属性排序排序结果如下(非打印):
result1和result2:
[('dave','B',10),('jane','B',12),('john','A',15)]result3和result4:
['john','A',15),('dave','B',10),('jane','B',12)]排序是为了确保稳定性和可靠性。当排序key对应的值相同时,它们在原始数据中的顺序将保持不变。例如,sort中的第三个例子如以下代码操作结果:
fromoperatorimportitemgetter
data=[('red',1),('blue',1),('red',2),('blue',2)]
print(sorted(data,key=itemgetter(0)))打印结果
[('blue',1),('blue',2),('red',1),('red',2)] 