bisect_left(*args, **kwargs)
Inserts a number into an array and returns the position where it should be inserted.
If this number does not exist in this array, return the index of the first number larger than this number.
If this number exists, return the minimum value of the position of this number in the array (that is, the leftmost index)
Case 1: This number does not exist in the array
arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]
# 在已排序的列表中查找元素 6 的插入位置
index = bisect_left(arr, 5.5)
print(f"Insert 6 at index {
index} to maintain sorted order.")
Results of the:
Insert 6 at index 4 to maintain sorted order.
We find the first number 6 that is greater than 5.5 and output 4
Case 2: This number exists in the array
Let’s modify the code and find the position of 6
from bisect import bisect_left, bisect, bisect_right
arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]
# 在已排序的列表中查找元素 6 的插入位置
index = bisect_left(arr, 6)
print(f"Insert 6 at index {
index} to maintain sorted order.")
Results of the:
Insert 6 at index 4 to maintain sorted order.
We found it was still 4
bisect_right(*args, **kwargs)
Inserts a number into an array and returns the position where it should be inserted.
Function: Returns the index of the first number larger than this number
Case 1: This number does not exist in the array
from bisect import bisect_left, bisect, bisect_right
arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]
# 在已排序的列表中查找元素 6 的插入位置
index = bisect_right(arr, 6.5)
print(f"Insert 6 at index {
index} to maintain sorted order.")
Results of the:
Insert 6 at index 6 to maintain sorted order.
The position of the number 7 is output
Case 2: This number exists in the array
from bisect import bisect_left, bisect, bisect_right
arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]
# 在已排序的列表中查找元素 6 的插入位置
index = bisect_right(arr, 6)
print(f"Insert 6 at index {
index} to maintain sorted order.")
Results of the:
Insert 6 at index 6 to maintain sorted order.
The position of the number 7 is output
Compare bisect_left and bisect_right
Similarity:
When the second parameter number x is not in the first parameter array arr, both will return the position of the first number in arr that is larger than x.
The difference:
when x exists in arr, bisect_left will return the smallest index of x in arr, and bisect_right will return the position of the first number larger than x.
bisect()
We looked at the source code and found:
bisect is bisect_right
Complete code
from bisect import bisect_left, bisect, bisect_right
arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]
# 在已排序的列表中查找元素 6 的插入位置
index = bisect_right(arr, 6)
print(f"Insert 6 at index {
index} to maintain sorted order.")
index = bisect(arr, 6)
print(f"Insert 6 at index {
index} to maintain sorted order.")
index = bisect_left(arr, 6)
print(f"Insert 6 at index {
index} to maintain sorted order.")
result:
Insert 6 at index 6 to maintain sorted order.
Insert 6 at index 6 to maintain sorted order.
Insert 6 at index 4 to maintain sorted order.
Source code analysis
Let’s first look at the source code of bisect_right
def bisect_right(a, x, lo=0, hi=None):
"""Return the index where to insert item x in list a, assuming a is sorted.
The return value i is such that all e in a[:i] have e <= x, and all e in
a[i:] have e > x. So if x already appears in the list, a.insert(x) will
insert just after the rightmost x already there.
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
# Use __lt__ to match the logic in list.sort() and in heapq
if x < a[mid]: hi = mid
else: lo = mid+1
return lo
Source code of bisect_left
def bisect_left(a, x, lo=0, hi=None):
"""Return the index where to insert item x in list a, assuming a is sorted.
The return value i is such that all e in a[:i] have e < x, and all e in
a[i:] have e >= x. So if x already appears in the list, a.insert(x) will
insert just before the leftmost x already there.
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
# Use __lt__ to match the logic in list.sort() and in heapq
if a[mid] < x: lo = mid+1
else: hi = mid
return lo
We observe that these two implementations mainly lie in the following two lines:
bisect_right:
if x < a[mid]: hi = mid
else: lo = mid+1
bisect_left:
if a[mid] < x: lo = mid+1
else: hi = mid
We observe that both pieces of source code will return lo, which is the left boundary, so we pay attention to the impact of these two lines of code on the left boundary:
In bisect_right, only when x=a[mid] or x>a[mid], lo will be updated to mid+1, so the final lo can only be the first index greater than x
in bisect_left. When a[mid] < x, lo will be updated to mid+1. At this time, what we want The index position must be on the right side of mid, so lo can be the position of the first occurrence of the same x; at the same time, we notice that when a[mid] >= x, hi=mid, which means that when lo gets the same number When it is the far left, the right endpoint of hi will actually be translated to the left, so lo can be the index of the first number greater than x in the array, or it can be the index of the first x on the left of the same x