bisect模块包含两个函数,bisect和insert,两个函数都利用二分查找算法在有序序列中查找或插入元素
用bisect来搜索
bisect(ordered_sequence, needle)
ordered_sequence:必须是一个有序的序列
needle:指定序列中需要搜索的位置数
ordered_sequence和needle只是举栗子的位置参数,无需关注
栗子:
gg = [33, 99, 77, 70, 89, 90, 100]
print(bisect.bisect(gg, 100))
运行后的结果如下
7
从运行的结果可以看出,查找的是元素插入的索引位置并返回出来,这点要注意...
bisect函数其实是bisect_right函数的别名,就是进行了赋值操作,图片如下:
再看下bisect_right函数的源码:
def insort_right(a, x, lo=0, hi=None):
"""Insert item x in list a, and keep it sorted assuming a is sorted.
If x is already in a, insert it to the right of the rightmost x.
Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if x < a[mid]: hi = mid
else: lo = mid+1
a.insert(lo, x)
首先是两个位置参数 :
a 就是我们要传 的有序的序列
b 就是我们要查询的元素值
其次是两个关键字参数,主要是用来缩小搜寻的范围:
lo 的默认值是0
hi 的默认值是None,但是又加了if判断,如果为None,默认值就变成了有序序列的长度,也就是len(a)
源码中的while处,是利用了二分查找算法在有序序列中查找元素,针对算法这块的可自行百度...
bisect_right函数还有一个姊妹函数叫bisect_left,区别如下
bisect_right:
若序列a中存在与x相同的元素,则返回x相等元素右侧插入点的索引位置
若序列a中不存在与x相同的元素,则返回与x左侧距离最近元素插入点的索引位置
栗子:
gg = [33, 70, 77, 89, 90, 99, 100]
print(bisect.bisect_right(gg, 100))
print(bisect.bisect_right(gg, 101))
运行后的结果如下
7
7
100存在列表中,返回右边插入点的索引位置是7;101在列表中不存在,取距离最近的插入点索引位置是也是7
bisect_left:
若序列a中存在与x相同的元素,则返回x相等元素左侧插入点的索引位置
若序列a中不存在与x相同的元素,则返回与x右侧距离最近元素插入点的索引位置
栗子:
gg = [33, 70, 77, 89, 90, 99, 100]
print(bisect.bisect_left(gg, 100))
print(bisect.bisect_left(gg, 101))
运行后的结果如下
6
7
100存在列表中,返回左边插入点的索引位置是6;101在列表中不存在,返回距离最近的插入点索引位置是7
使用bisect()函数来进行数字表查询,从一个给定的考试成绩集合里,通过一个有序的数字表,查出其对应的字符等级:90分及以上的是’A‘,80到89是’B‘,以此类推...
栗子:
def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
i = bisect.bisect(breakpoints, score)
return grades[i]
ll = [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
print(ll)
运行后的结果如下
['F', 'A', 'C', 'C', 'B', 'A', 'A']
score为33时,插入点索引位置为0,取值是F
score为99时,插入点索引位置为4,取值是A
score为77时,插入点索引位置为2,取值是C
score为70时,插入点索引位置为2,取值是C
score为89时,插入点索引位置为3,取值是B
score为90时,插入点索引位置为4,取值是A
score为100时,插入点索引位置为4,取值是A
用insort来插入
insort(ordered_sequence, needle)
ordered_sequence:必须是一个有序的序列
needle:指定序列中需要搜索的位置数
ordered_sequence和needle只是举栗子的位置参数,无需关注
栗子:
gg = [33, 70, 77, 89, 90, 99, 100]
bisect.insort(gg, 50)
print(gg)
运行后的结果如下
[33, 50, 70, 77, 89, 90, 99, 100]
从上述结果显示可以看出,数据插入时不会破坏有序的列表,相反插入的数据还是自动排序好的
insort函数其实是insort_right函数的别名,就是进行了赋值操作,图片如下:
insort_right函数还有一个姊妹函数叫insort_left,区别如下
insort_right:
若序列a中存在与x相同的元素,则返回x相等元素右侧插入点的索引位置并执行真正的插入
若序列a中不存在与x相同的元素,则返回与x左侧距离最近元素插入点的索引位置并执行真正的插入
首先插入序列中不存在的数据
栗子:
gg = [33, 70, 77, 89, 90, 99, 100]
print(bisect.bisect_right(gg, 50))
bisect.insort_right(gg, 50)
print(gg)
运行后的结果如下
1
[33, 50, 70, 77, 89, 90, 99, 100]
上述代码中使用bisect_right函数查到插入点索引位置为1,运行后插入到70前面,也就是索引1的位置
其次插入序列中存在的数据
栗子:
gg = [33, 70, 77, 89, 90, 99, 100]
print(bisect.bisect_right(gg, 70))
bisect.insort_right(gg, 70)
print(gg)
运行后的结果如下
2
[33, 70, 70, 77, 89, 90, 99, 100]
上述代码中使用bisect_right函数查询出插入点索引位置为2,运行后插入到70后面,也就是索引2的位置
最后就是insort_left函数
insort_left:
若序列a中存在与x相同的元素,则返回x相等元素左侧插入点的索引位置并执行真正的插入
若序列a中不存在与x相同的元素,则返回与x右侧距离最近元素插入点的索引位置并执行真正的插入
insort_left的插入可自行操作以便增加理解,可能刚开始对bisect查询返回的插入索引位置有些迷惑,多操作几遍就慢慢理解了...
以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,评论区留言会及时修正发布,谢谢!
微信搜索公众号:就用python