bisect.bisect_left 是 Python 标准库 bisect 模块中的一个重要函数,用于在已排序的序列中快速查找元素的插入位置。它的核心功能是维护列表的有序性,非常适合用于插入、查找等场景。
bisect_left(a, x, lo=0, hi=len(a), *, key=None) 会在有序列表 a 中查找元素 x 应该插入的位置,返回的插入点位置是第一个不小于 x 的元素的位置(即所有在插入点左侧的元素都小于 x)。
import bisect
nums = [1, 3, 5, 7, 9]
# 查找已存在元素
x = 5
pos = bisect.bisect_left(nums, x)
print(pos) # 输出:2
# 解释:5已存在于列表中,返回其最左侧位置(索引2)
# 查找不存在元素
x = 6
pos = bisect.bisect_left(nums, x)
print(pos) # 输出:3
# 解释:6介于5和7之间,插入后列表仍有序,位置为3nums = [1, 3, 5, 7, 9]
x = 4
# 只在nums[1:4](即[3,5,7])中查找
pos = bisect.bisect_left(nums, x, lo=1, hi=4)
print(pos) # 输出:2
# 解释:在子列表[3,5,7]中,4应插入在3和5之间,对应原列表索引2当列表元素是字典、对象等复杂结构时,可以使用 key 参数指定比较的字段:
students = [
{"name": "Alice", "age": 18},
{"name": "Bob", "age": 20},
{"name": "Charlie", "age": 22}
]
# 按"age"字段查找插入位置
age_to_insert = 21
pos = bisect.bisect_left(students, age_to_insert, key=lambda s: s["age"])
print(pos) # 输出:2
# 解释:21介于20和22之间,插入位置为2,保持按年龄有序bisect_right 的区别bisect_left 和 bisect_right(或简称 bisect)的主要区别在于处理重复元素时:
bisect_left 返回插入点位置是第一个不小于 x 的元素的位置bisect_right 返回插入点位置是第一个大于 x 的元素的位置nums = [1, 3, 3, 3, 5]
print(bisect.bisect_left(nums, 3)) # 输出:1
print(bisect.bisect_right(nums, 3)) # 输出:4# 使用bisect_left实现高效的成员检查
def contains(a, x):
i = bisect.bisect_left(a, x)
return i != len(a) and a[i] == x
nums = [1, 3, 5, 7, 9]
print(contains(nums, 5)) # True
print(contains(nums, 6)) # Falsebisect_left 的时间复杂度是 O(log n),比线性搜索 O(n) 高效得多,特别适合处理大型有序数据集。