邀请大神——二分查找
Posted 数据有度
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了邀请大神——二分查找相关的知识,希望对你有一定的参考价值。
前言
bisect
是Python内置实现的二分查找。在实际工作中的某些场景,比如学生成绩分级,可协助你写出优雅的代码。
需求
你需要将学生的成绩(0-100)转换成等级(ABCDEF)。
方案
新手方案
二话不说,if
判断走起。
# codeing:utf-8
def grade(score):
if score < 60:
return 'F'
elif score < 70:
return 'E'
elif score < 80:
return 'D'
elif score < 90:
return 'C'
elif score < 100:
return 'B'
else:
return 'A'
if __name__ == '__main__':
scores = [59, 60, 65, 70, 78, 80, 89, 90, 95, 100]
result = [grade(i) for i in scores]
print(result)
# ['F', 'E', 'E', 'D', 'D', 'C', 'C', 'B', 'B', 'A']
很好,我们出色地完成了任务。随后我们还需要按照学生的学时,商城会员的积分来进行分级。看来我们还需要茫茫多的if--elif--else
判断。
Pythonic方案
仔细分析一下,类似的场景其实都包含了两个关键信息。一个是分界点,另外一个是等级。
比如学生成绩分级的分界点是[60, 70, 80, 90, 100]
,等级是'FEDCBA'
。
将成绩转换为分级的逻辑其实就是两步:
在分界点(
breakpoints
)中找到学生成绩对应的位置(index)返回等级(
grades
)对应位置(index)的结果
# codeing:utf-8
from bisect import bisect
def grade(score, breakpoints=[60, 70, 80, 90, 100], grades='FEDCBA'):
i = bisect(breakpoints, score)
return grades[i]
if __name__ == '__main__':
scores = [59, 60, 65, 70, 78, 80, 89, 90, 95, 100]
result = [grade(i) for i in scores]
print(result)
# ['F', 'E', 'E', 'D', 'D', 'C', 'C', 'B', 'B', 'A']
同样地,根据商城会员的积分来进行分级。
breakpoints = [1000, 2000, 3000]
grades = ['普通会员', '中级会员', '高级会员', 'VIP']
scores = [499, 1023, 2020, 3000, 4999]
print([grade(i, breakpoints=breakpoints, grades=grades) for i in scores])
# ['普通会员', '中级会员', '高级会员', 'VIP', 'VIP']
总结
防踩坑Tips:
grades
的元素应该比breakpoints
多一个(可以想想原因)。bisect
模块提供了bisect_left
和bisect_right
两个方法,区别在于当元素相等时,返回的index
是在breakpoint
的左边还是右边。例子中用的
bisect.bisect
就是bisect_right
。更详细的说明,请参看Python官方文档
bisect — Array bisection algorithm
孤立地来看bisect
,可能会觉得仅仅是二分查找而已。然而在工作中,根据场景使用bisect
,往往会给你带来惊喜。这里其实还是一个应用算法的能力。
有空也可以多翻翻Python文档,很多内置库都提供了方便的功能。比如上面学生成绩分级的例子就是官方文档提供的。
练习
请使用bisect_left
改写例子中的代码。
以上是关于邀请大神——二分查找的主要内容,如果未能解决你的问题,请参考以下文章