您的位置:首页 > 编程语言 > Python开发

Python bisect模块的使用方法及源码实现

2018-12-29 17:05 92 查看

在平时使用python对list进行操作时,有时候会遇到这种情况:我们想要向一个已经排序好的list插入新元素,但不想改变原list的顺序,也就是说新元素的目标是插入到符合原list顺序的位置(比如数字2作为新元素被插入list[1, 3, 4]后,list应变成[1, 2, 3, 4]),bisect模块刚好可以实现这个简单的需求。

bisect模块提供了如下几个方法:

假设a为一个有序的list,x为新元素,lo和hi作为边界index规定了函数的一个查询子集(即a[lo: hi])。

  1. bisect.bisect_left(a, x, lo=0, hi=len(a))
def bisect_left(a, x, lo=0, hi=None):
"""返回x插入a后所在位置的index(如果a中存在与x等值的元素,则插入到左侧)"""

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 a[mid] < x: lo = mid+1
else: hi = mid
return lo
  1. bisect.bisect_right(a, x, lo=0, hi=len(a))
def bisect_right(a, x, lo=0, hi=None):
"""返回x插入a后所在位置的index(如果a中存在与x等值的元素,则插入到右侧)"""

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
return lo
  1. bisect.insort_left(a, x, lo=0, hi=len(a))
def insort_left(a, x, lo=0, hi=None):
"""将x插入a(如果a中存在与x等值的元素,则插入到左侧)"""

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 a[mid] < x: lo = mid+1
else: hi = mid
a.insert(lo, x)
  1. bisect.insort_right(a, x, lo=0, hi=len(a))
def insort_right(a, x, lo=0, hi=None):
"""将x插入a(如果a中存在与x等值的元素,则插入到右侧)"""

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)

ps. 如果lo和hi是大于len(a)的数字,以上函数并不会报错或者仅仅出现list index out of range的错误,而是会耐心的去把x插入到a[lo: hi]中(因为此时a[lo: hi]为[],故x肯定会作为第一个元素插入到这个空子集内,index的返回结果也必为lo)。这种错误的用法当然也会导致错误的结果,导致新元素被排在了a的最后。

参考 https://docs.python.org/2/library/bisect.html#module-bisect

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: