当前位置: 首页 > news >正文

python operator 多属性排序_Python应用——自定义排序全套方案

1d77f5bef7e2a9c6787d6b6904e26533.png

本文始发于个人公众号:TechFlow,原创不易,求个关注

今天的这篇文章和大家聊聊Python当中的排序,和很多高级语言一样,Python封装了成熟的排序函数。我们只需要调用内部的sort函数,就可以完成排序。但是实际场景当中,排序的应用往往比较复杂,比如对象类型,当中有多个字段,我们希望按照指定字段排序,或者是希望按照多关键字排序,这个时候就不能简单的函数调用来解决了。

字典排序

我们先来看下最常见的字典排序的场景,假设我们有一个字典的数组,字典内有多个字段。我们希望能够根据字典当中的某一个字段来进行排序,我们用实际数据来举个例子:

kids 

这里的kids是一个dict类型的数组,dict当中拥有name, score和age三个字段。假设我们当下希望能够按照score来排序,应该怎么办呢?

对于这个问题,解决的方案有很多,首先,我们可以使用上一篇文章当中提到的匿名函数来指定排序的。这里的用法和上篇文章优先队列的用法是一样的,我们直接来看代码:

sorted

在匿名函数当中我们接收的x是kids当中的元素,也就是一个dict,所以我们想要指定我们希望的字段,需要用dict访问元素的方法,也就是用中括号来查找对应字段的值。

假如我们希望按照多关键字排序呢?

首先介绍一下多关键字排序,还是用上面的数据打比方。在上面的例子当中,各个kid的score都不一样,所以排序的结果是确定的。但如果存在两个人的score相等,我希望年龄小的排在前面,那么应该怎么办呢?我们分析一下可以发现,原本是按照分数从小到大排序,但有可能会出现分数相等的情况。这个时候,我们希望能够按照在分数相等的情况下来比较年龄,也就是说我们希望根据两个关键字来排序,第一个关键字是分数,第二个关键字是年龄。

由于Python当中支持tuple和list类型的排序,也就是说我们可以直接比较[1, 3]和[1, 2]的大小关系,Python会自动一次比较两个数组当中的元素的大小。如果相等就自动往后比较,直到出现不等或者结束为止。

明白了这点,其实就很好办了。我们只要在匿名函数当中稍稍修改,让它返回的结果增加一个字段即可。

sorted

itemgetter

除了匿名函数,Python也有自带的库可以解决这个问题。用法和匿名函数非常接近,使用起来稍稍容易一些。

它就是operator库当中的itemgetter函数,我们直接来看代码:

from 

如果是多关键字也可以,传入多个key即可:

sorted(kids, key=itemgetter('score', 'age'))

对象排序

我们接下来看一下对象的自定义排序,我们首先把上面的dict写成对象:

class 

为了方便观察打印结果,我们重载了__repr__方法,可以简单地将它当做是Java当中的toString方法,这样我们可以指定在print它的时候的输出结果。

同样,operator当中也提供了对象的排序因子函数,用法上和itemgetter一样,只是名字不同。

from 

我们也可以使用匿名函数lambda来实现:

sorted

自定义排序

到这里还没有结束,因为仍然存在一些问题解决不了。虽然我们实现了多关键字排序,但是还有一个问题解决不了,就是排序的顺序问题。

我们可以在sorted函数的参数当中传入reverse=True来控制是正序还是倒叙,但是如果我使用多关键字,想要按照某个关键字升序,某个关键字降序怎么办?举个例子,比如说我们想要按照分数降序,年龄升序就没办法通过reverse来解决了,这就是当前解决不了的问题。

那应该怎么办呢?

这个时候就需要终极排序杀器上场了,也就是标题当中所说的自定义排序。也就是说我们自己实现一个定义元素大小的函数,然后让sorted来调用我们这个函数来完成排序。这也是C++和Java等语言的用法。

自定义的函数并不难写,我们随手就来:

def 

如果看不明白,也没关系,我写成完整版:

def 

写完了之后,还没有结束,这个函数是不能直接投入使用的,他和我们之前提到的lambda匿名函数是不一样的。之前的匿名函数只是用来指定字段的,所以我们不能直接将这个函数传递给key,还需要在外面包一层加工处理才可以。不过这一层处理函数Python也已经有现成的工具了,我们可以直接调用,它在functools里,我们来看代码:

from 

我们来看一下cmp_to_key函数里的源码:

def 

我们可以看到,在函数内部,它其实定义了一个类,然后在类当中重载了比较函数,最后返回的是一个重载了比较函数的新的对象。这些__lt__, __gt__函数就是类当中重载的比较函数。比如__lt__是小于的判断函数,__eq__是相等的函数。那么问题来了,我们能不能直接在Kid类当中重载比较函数呢,这样就可以直接排序了。

答案是确定的,我们当然可以这么办,实际上这也是面向对象当中非常常用的做法。相比于自定义比较函数,我们往往更倾向于在类当中定义好优先级。Python当中实现的方法也很简单,就是我们手动实现一个__lt__函数,sorted默认会将小的元素排在前面,所以我们只用实现__lt__一个函数就够了。这个函数当中传入的参数是另一个对象,我们直接在函数里面写清楚比较逻辑就行了。返回True表示当前对象比other小,否则比other大。

我们附上完整代码:

class 

实现了比较函数之后,我们直接调用sorted,不用任何其他传参就可以对它进行排序了。

今天的内容虽然难度不大,但是在我们日常编程当中非常常用,经常会出现需要对复杂的对象和内容进行排序的情况,所以希望大家都掌握,因为一定会派上用场的。

今天的文章就是这些,如果觉得有所收获,请顺手扫码点个关注吧,你们的举手之劳对我来说很重要。

8069c26cbf1d20974fc54f895f349b90.png

相关文章:

  • 随机森林原始论文_初识随机森林
  • CNN Matlab例子RGB_CNN网络基础
  • js date 当前日志往后一个月_因为造轮子,我一个月就转正了 | 原力计划
  • apache tomcat下32还是64_Tomcat 下载、安装、配置图文教程
  • sqlserver安装目录_Windows 2016中安装SQLServer2016 Failover Cluster
  • springmvc @requestbody_【面试系列7】Spring MVC
  • python实现程序安装_python实现查找所有程序的安装信息
  • python中os模块_python中的os模块
  • 怎么python画好几朵玫瑰花_怎么用python画玫瑰花,求大神贴代码,感激不尽
  • 51单片机电路原理图_10个定时器精选电路方案带你学习时钟脉冲的工作方式
  • python读取数据的函数详解_python如何从文件读取数据及解析
  • wxpython的安装步骤_wxPython的安装图文教程(Windows)
  • python findall函数_python re模块findall()函数实例解析
  • pip环境变量配置 python3.6_win10下Python3.6安装、配置以及pip安装教程
  • python卸载opencv_python怎么卸载opencv-问答-阿里云开发者社区-阿里云
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • 07.Android之多媒体问题
  • css选择器
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • Facebook AccountKit 接入的坑点
  • javascript从右向左截取指定位数字符的3种方法
  • Lsb图片隐写
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • Yii源码解读-服务定位器(Service Locator)
  • 关于字符编码你应该知道的事情
  • 简单数学运算程序(不定期更新)
  • 聚簇索引和非聚簇索引
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 深入浏览器事件循环的本质
  • 我有几个粽子,和一个故事
  • 一个JAVA程序员成长之路分享
  • 一天一个设计模式之JS实现——适配器模式
  • k8s使用glusterfs实现动态持久化存储
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • #Z0458. 树的中心2
  • (2022 CVPR) Unbiased Teacher v2
  • (C#)获取字符编码的类
  • (LeetCode C++)盛最多水的容器
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (三分钟)速览传统边缘检测算子
  • (一)Java算法:二分查找
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • ... 是什么 ?... 有什么用处?
  • .net Signalr 使用笔记
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .netcore 获取appsettings
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .NET上SQLite的连接
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • @Documented注解的作用
  • @NestedConfigurationProperty 注解用法