python字典按值的⼤⼩排序_Python应⽤——⾃定义排序全套
⽅案
今天的这篇⽂章和⼤家聊聊Python当中的排序,和很多⾼级语⾔⼀样,Python封装了成熟的排序函数。我们只需要调⽤内部的sort函数,就可以完成排序。但是实际场景当中,排序的应⽤往往⽐较复杂,⽐如对象类型,当中有多个字段,我们希望按照指定字段排序,或者是希望按照多关键字排序,这个时候就不能简单的函数调⽤来解决了。
字典排序
我们先来看下最常见的字典排序的场景,假设我们有⼀个字典的数组,字典内有多个字段。我们希望能够根据字典当中的某⼀个字段来进⾏排序,我们⽤实际数据来举个例⼦:
这⾥的kids是⼀个dict类型的数组,dict当中拥有name, score和age三个字段。假设我们当下希望能够按照score来排序,应该怎么办呢?
对于这个问题,解决的⽅案有很多,⾸先,我们可以使⽤上⼀篇⽂章当中提到的匿名函数来指定排序的。这⾥的⽤法和上篇⽂章优先队列的⽤法是⼀样的,我们直接来看代码:
在匿名函数当中我们接收的x是kids当中的元素,也就是⼀个dict,所以我们想要指定我们希望的字段,需要⽤dict访问元素的⽅法,也就是⽤中括号来查对应字段的值。
假如我们希望按照多关键字排序呢?
⾸先介绍⼀下多关键字排序,还是⽤上⾯的数据打⽐⽅。在上⾯的例⼦当中,各个kid的score都不⼀样,所以排序的结果是确定的。但如果存在两个⼈的score相等,我希望年龄⼩的排在前⾯,那么应该怎么办呢?我们分析⼀下可以发现,原本是按照分数从⼩到⼤排序,但有可能会出现分数相等的情况。这个时候,我们希望能够按照在分数相等的情况下来⽐较年龄,也就是说我们希望根据两个关键字来排序,第⼀个关键字是分数,第⼆个关键字是年龄。
由于Python当中⽀持tuple和list类型的排序,也就是说我们可以直接⽐较[1, 3]和[1, 2]的⼤⼩关系,Python会⾃动⼀次⽐较两个数组当中的元素的⼤⼩。如果相等就⾃动往后⽐较,直到出现不等或者结束为⽌。
明⽩了这点,其实就很好办了。我们只要在匿名函数当中稍稍修改,让它返回的结果增加⼀个字段即可。
itemgetter
除了匿名函数,Python也有⾃带的库可以解决这个问题。⽤法和匿名函数⾮常接近,使⽤起来稍稍容易⼀些。
它就是operator库当中的itemgetter函数,我们直接来看代码:
如果是多关键字也可以,传⼊多个key即可:
对象排序
我们接下来看⼀下对象的⾃定义排序,我们⾸先把上⾯的dict写成对象:
为了⽅便观察打印结果,我们重载了__repr__⽅法,可以简单地将它当做是Java当中的toString⽅法,这样我们可以指定在print它的时候的输出结果。
同样,operator当中也提供了对象的排序因⼦函数,⽤法上和itemgetter⼀样,只是名字不同。
我们也可以使⽤匿名函数lambda来实现:
⾃定义排序
到这⾥还没有结束,因为仍然存在⼀些问题解决不了。虽然我们实现了多关键字排序,但是还有⼀个问题解决不了,就是排序的顺序问题。
我们可以在sorted函数的参数当中传⼊reverse=True来控制是正序还是倒叙,但是如果我使⽤多关键字,想要按照某个关键字升序,某个关键字降序怎么办?举个例⼦,⽐如说我们想要按照分数降序,年龄升序就没办法通过reverse来解决了,这就是当前解决不了的问题。
那应该怎么办呢?
这个时候就需要终极排序杀器上场了,也就是标题当中所说的⾃定义排序。也就是说我们⾃⼰实现⼀个定义元素⼤⼩的函数,然后让sorted 来调⽤我们这个函数来完成排序。这也是C++和Java等语⾔的⽤法。
⾃定义的函数并不难写,我们随⼿就来:
如果看不明⽩,也没关系,我写成完整版:
写完了之后,还没有结束,这个函数是不能直接投⼊使⽤的,它和我们之前提到的lambda匿名函数是
不⼀样的。之前的匿名函数只是⽤来指定字段的,所以我们不能直接将这个函数传递给key,还需要在外⾯包⼀层加⼯处理才可以。不过这⼀层处理函数Python也已经有现成的⼯具了,我们可以直接调⽤,它在functools⾥,我们来看代码:
我们来看⼀下cmp_to_key函数⾥的源码:
我们可以看到,在函数内部,它其实定义了⼀个类,然后在类当中重载了⽐较函数,最后返回的是⼀个重载了⽐较函数的新的对象。这些
__lt__, __gt__函数就是类当中重载的⽐较函数。⽐如__lt__是⼩于的判断函数,__eq__是相等的函数。那么问题来了,我们能不能直接在Kid类当中重载⽐较函数呢,这样就可以直接排序了。
答案是确定的,我们当然可以这么办,实际上这也是⾯向对象当中⾮常常⽤的做法。相⽐于⾃定义⽐较函数,我们往往更倾向于在类当中定义好优先级。Python当中实现的⽅法也很简单,就是我们⼿动实现⼀个__lt__函数,sorted默认会将⼩的元素排在前⾯,所以我们只⽤实现__lt__⼀个函数就够了。这个函数当中传⼊的参数是另⼀个对象,我们直接在函数⾥⾯写清楚⽐较逻辑就⾏了。返回True表⽰当前对象⽐other⼩,否则⽐other⼤。能运行python的软件
我们附上完整代码:
实现了⽐较函数之后,我们直接调⽤sorted,不⽤任何其他传参就可以对它进⾏排序了。
今天的内容虽然难度不⼤,但是在我们⽇常编程当中⾮常常⽤,经常会出现需要对复杂的对象和内容进⾏排序的情况,所以希望⼤家都掌握,因为⼀定会派上⽤场的。
今天的⽂章就是这些,如果觉得有所收获,请顺⼿点个关注或转发吧,你们的举⼿之劳对我来说很重要。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。