偶然看到了 stackoverflow 上的一个问题,还挺有启发,故分享一下。

题目大意是:有从 A 到 F 的 5 个等级,现要判断某个数值(从 0 到 1 之间)所属的等级。举例,如数值 >= 0.9,则属于 A;若数值 >= 0.8,则属于 B;以此类推。

若使用 if-elif 语句,可能会写成这样:

if scr >= 0.9:
print('A')
elif scr >= 0.8:
print('B')
elif scr >= 0.7:
print('C')
elif scr >= 0.6:
print('D')
else:
print('F')

此写法出现了很多重复的模式,不够简洁优雅。有什么更好的写法,来实现这个目的呢?

该问题下的回答挺多的,实现思路五花八门。我挑几个可读性比较好:

方法一:使用bisect 模块(数字可调)

方法二:使用 zip() 与 next()

方法三:使用字典(仅适用于 Python 3.6 以上的有序字典)

还有其它几个回答,虽然都能实现数字分级的目的,但是其可读性要差很多,因为它们要么需要你作计算和推理,要么就是引入了额外的变量。

感兴趣的话,你可在这个地址查看全部答案:https://stackoverflow.com/questions/61030617/how-can-i-simplify-repetitive-if-elif-statements

纵观全部答案后,我认为还是使用bisect 的方法最高效优雅,不愧是它获得了最高的赞同票。

这里简单分析下它的实现过程。

bisect 是 Python 内置的标准库,实现了二分查找算法。所谓二分查找,也被称为“折半查找”(Binary Search),其基本思想是把有序排列的 n 个元素平均分成两半,然后将待查找的 x 与中间元素比较,若 x 小于中间元素,则将左半段二分,再将 x 与其中间元素比对,以此类推。

这是一个简单的图示例子:

bisect 库中的 bisect() 方法,查找元素 x 在一个升序序列中的插入点 i,使得插入点左侧的元素都小于等于 x,插入点右侧的元素都大于 x。

对照前面的例子:

from bisect import bisect 

def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
i = bisect(breakpoints, score)
return grades[i]

可以化简成两部分:

  • bisect([60, 70, 80, 90], score),返回插入点的值。假如 score 是 59,计算得出插入点在 60 的左侧,而 Python 列表的索引值是以 0 开始,所以返回插入点的值为 0;假如 score 是 60,计算得出插入点在 60 的右侧,即返回索引值为 1。
  • 'FDCBA'[i],返回索引值为 i 的字符。假如 i 是 0,得到“F”;假如 i 是 3,得到“B”……

二分查找算法是效率较高的算法,时间复杂度为 O(logn)。该题目的查找范围很小,所以时间效率差别不大。但是其写法称得上是 Pythonic,值得借鉴。

另外,再看看前面的方法三(使用字典),它的可读性很强,即顺次将 scr 与字典中的值比较(从高往低,即 0.9~0.5),以此得出对应的键值。(PS:它多分了一个“E”级,可去掉)

如果 Python 版本低于 3.6,则 grades.items() 会是无序的,将会破坏比较的顺序。为了兼容性,可以修改成 sorted(grades.items()):

这种写法没有引入额外的库,使用的 items() 与 sorted() 都是基础知识(相比于方法二的 zip() 与 next()),简单实用,也非常值得推荐。

不管怎么说,反复使用 if-elif 语句的判断方式是挺笨拙的,必须改进。文中列出的都是目前比较受认可的回答。

如果有面试官把它作为面试题,我觉得会挺有意思:难度不大,有发挥空间。

读者们可有其它想法?欢迎留言讨论。

不使用 if-elif 语句,如何优雅地判断某个数字所属的等级?的更多相关文章

  1. Python新手学习基础之条件语句——elif语句

    elif语句 (相当于C语言的else if) 在Python中,当我们需要有更多的判断条件时,我们往往会使用另外一种语法表达,即使用elif: if 判断条件1: 执行语句1 elif 判断条件2: ...

  2. python语句结构(if判断语句)

    一.python语句结构分类 条件控制语句:if 语句 if....elif语句 if嵌套 循环语句:while语句    for循环 控制语句:break.continue.pass语句 二.pyt ...

  3. sql 语句中使用条件判断case then else end

    sql 语句中使用条件判断case then else end范例: SELECT les.[nLessonNo] FROM BS_Lesson AS les WHERE les.[sClassCod ...

  4. [原创小知识] 如何优雅的判断 ie 版本

    之前一直不怎么做低版本ie的前端,毕竟ie的大半江山都被chrome 霸占,但大部分情况下,却还是要去兼容下那些老顽固.一切的原因,都是因为当年微软的年轻气盛,喜欢另起炉灶,真是很无语. 通常我们去h ...

  5. Oracle的sql语句的两种判断形式

    Oracle的sql语句的两种判断形式 判断当前列同时改动当前列 判断一个情况改动其他值 一类情况详解:实现的是当num这一列的值为3时,就显示好 以此类推 1)case num when 3 the ...

  6. 搬砖的也能学Python----if - elif 语句

    引入:如果平时执行的过程超过两个分支,则使用if-elif语句 if-elif 语句结构 if 判断条件: 要执行的代码 elif 判断条件: 要执行的代码 -- else: 要执行的代码 判断条件: ...

  7. C#中一种替换switch语句更优雅的写法

    今天在项目中遇到了使用switch语句判断条件,但问题是条件比较多,大概有几十个条件,满屏幕的case判断,是否有更优雅的写法替代switch语句呢? 假设有这样的一个场景:商场经常会根据情况采取不同 ...

  8. if..elif语句

    根据用户输入内容打印其权限 # alex --> 超级管理员 # eric --> 普通管理员 # tony,rain --> 业务主管 # 其他 --> 普通用户 name ...

  9. 输出,变量的使用,子查询,逻辑语句,循环,case..when..then..end多分支语句,Exists(判断存在)

    --------------输出----------------print 'hello world'--以文本形式输出select 'hello world'--以网格形式输出,也可以设置成以文本形 ...

随机推荐

  1. 性能测试从零开始-LoadRunner入门

    写在前面 又到了公司每月的读书会,经过上个月的试运行后,公司把读书会纳入每月的绩效考核中,听到这个消息,当时我的内心是崩溃的,不过从另一方面来讲,对于我来说也一件好事儿,这样可以督促自己养成读书的习惯 ...

  2. hdu1495 倒水bfs

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/1495/ 题意:给定三个杯子S,M,N,满足S=M+N,现在要求用最短的次数将S杯中的饮倒平分到两个杯子中.我们首 ...

  3. 题解 P2755 【洗牌问题】

    这是本人的第一篇题解 请多多宽恕 这一道题其实不要用数组 我们来观察一下n=3时的情况: 原: 1 2 3 4 5 6 4 1 5 2 6 3 2 4 6 1 3 5 1 2 3 4 5 6 我们去观 ...

  4. UCF Local Programming Contest 2016 J题(二分+bfs)

    题目链接如下: https://nanti.jisuanke.com/t/43321 思路: 显然我们要采用二分的方法来寻找答案,给定一个高度如果能确定在这个高度时是否可以安全到达终点,那我们就可以很 ...

  5. PHP之从反向删除单链表元素的问题谈起

    在完成一个单链表的删除指定元素的题目中,我发现了一件神奇的事情,php对象赋值给另外一个变量后,可以如同引用传值一般继续利用新的变量来实现链表的链接. 后面经过查证后发现: PHP7.0版本除了对象, ...

  6. MySQL对JSON类型UTF-8编码导致中文乱码探讨

    前言 继上文发表之后,结合评论意见并亲自验证最终发现是编码的问题,但是对于字符编码还是有点不解,于是乎,有了本文,我们来学习字符编码,在学习的过程中,我发现对于MySQL中JSON类型的编码导致数据中 ...

  7. Java的集合框架综述

    集合 用于存储和管理数据的实体被称为数据结构(data structure).数据结构可用于实现具有不同特性的集合对象,这里所说的集合对象可以看作一类用于存储数据的特殊对象. 集合内部可以采用某种数据 ...

  8. Sublimeの虚拟环境(Venv)设置

    这里主要介绍,在使用 Python 虚拟环境(Venv)时,SublimeText 该怎么设置 为什么使用虚拟环境(Venv) 因为,我有洁癖! 我就是喜欢看到,pip list 命令下什么 Pack ...

  9. EF多租户实例:快速实现分库分表

    前言 来到这篇随笔,我们继续演示如何实现EF多租户. 今天主要是演示多租户下的变形,为下图所示 实施 项目结构 这次我们的示例项目进行了精简,仅有一个API项目,直接包含所有代码. 其中Control ...

  10. 事务框架之声明事务(自动开启,自动提交,自动回滚)Spring AOP 封装

    利用Spring AOP 封装事务类,自己的在方法前begin 事务,完成后提交事务,有异常回滚事务 比起之前的编程式事务,AOP将事务的开启与提交写在了环绕通知里面,回滚写在异常通知里面,找到指定的 ...