page contents

Python bisect : 维持列表的有序状态!

今天给大家介绍一个超实用的 Python 内置模块——bisect。它的核心功能很简单:让列表始终保持有序状态,而且不用每次添加元素后都调用 sort 方法。

attachments-2025-10-38OkQLcf68f832ee23fb7.png今天给大家介绍一个超实用的 Python 内置模块——bisect。它的核心功能很简单:让列表始终保持有序状态,而且不用每次添加元素后都调用 sort 方法

对于需要频繁插入元素又要保持顺序的场景,这简直是效率神器!

为什么需要 bisect

平时我们维护有序列表时,通常是先把元素随便插进列表,最后再调用 sort() 排序。但如果需要频繁插入,每次都重新排序就太浪费时间了。

bisect 模块的厉害之处在于,它会直接找到新元素应该插入的位置,然后把元素放进去,全程保持列表有序,省去了反复排序的麻烦。

基础用法:插入元素并保持有序

先看一个简单例子,用 insort() 函数向列表中插入元素,列表会自动维持有序状态:

import bisect

# 一组随机数字
values = [148577265045667910384771]

print('New  Pos  Contents')
print('---  ---  --------')

l = []
for i in values:
    position = bisect.bisect(l, i)  # 找到插入位置
    bisect.insort(l, i)  # 插入元素并保持有序
    print(f'{i:3}  {position:3}', l)

运行结果如下:

$ python3 bisect_example.py

New  Pos  Contents
---  ---  --------
 14    0 [14]
 85    1 [14, 85]
 77    1 [14, 77, 85]
 26    1 [14, 26, 77, 85]
 50    2 [14, 26, 50, 77, 85]
 45    2 [14, 26, 45, 50, 77, 85]
 66    4 [14, 26, 45, 50, 66, 77, 85]
 79    6 [14, 26, 45, 50, 66, 77, 79, 85]
 10    0 [10, 14, 26, 45, 50, 66, 77, 79, 85]
  3    0 [3, 10, 14, 26, 45, 50, 66, 77, 79, 85]
 84    9 [3, 10, 14, 26, 45, 50, 66, 77, 79, 84, 85]
 77    8 [3, 10, 14, 26, 45, 50, 66, 77, 77, 79, 84, 85]
  1    0 [1, 3, 10, 14, 26, 45, 50, 66, 77, 77, 79, 84, 85]

结果解读:

  • 第一列是新插入的数字;
  • 第二列是该数字在列表中插入的位置;
  • 第三列是插入后的有序列表。

可以看到,每插入一个元素,列表始终保持从小到大的顺序,完全不用手动排序!

小提醒:什么时候用 bisect 更划算?

上面的例子数据量很小,可能感觉和「先插入再排序」差别不大。但如果是数据量很大、插入频繁的场景(比如实时数据处理),bisect 的优势就明显了:

  • 避免了反复排序的耗时(排序算法时间复杂度通常是 O(n log n));
  • 插入操作的时间复杂度是 O(n),但定位插入位置用了二分查找(O(log n)),整体更高效。

尤其是当列表元素的比较操作很耗时(比如复杂对象),bisect 能省更多时间。

进阶技巧:处理重复元素

如果列表中出现重复元素,bisect 提供了两种插入策略:

  • 插在现有相同元素的右边(默认行为,insort_right());
  • 插在现有相同元素的左边insort_left())。

insort() 其实是 insort_right() 的别名,来看两者的区别:

import bisect

# 同样的随机数字
values = [148577265045667910384771]

print('New  Pos  Contents')
print('---  ---  --------')

# 使用 bisect_left 和 insort_left
l = []
for i in values:
    position = bisect.bisect_left(l, i)  # 找到左侧插入位置
    bisect.insort_left(l, i)  # 插在相同元素左边
    print(f'{i:3}  {position:3}', l)

运行结果:

$ python3 bisect_example2.py

New  Pos  Contents
---  ---  --------
 14    0 [14]
 85    1 [14, 85]
 77    1 [14, 77, 85]
 26    1 [14, 26, 77, 85]
 50    2 [14, 26, 50, 77, 85]
 45    2 [14, 26, 45, 50, 77, 85]
 66    4 [14, 26, 45, 50, 66, 77, 85]
 79    6 [14, 26, 45, 50, 66, 77, 79, 85]
 10    0 [10, 14, 26, 45, 50, 66, 77, 79, 85]
  3    0 [3, 10, 14, 26, 45, 50, 66, 77, 79, 85]
 84    9 [3, 10, 14, 26, 45, 50, 66, 77, 79, 84, 85]
 77    7 [3, 10, 14, 26, 45, 50, 66, 77, 77, 79, 84, 85]  # 注意这里的位置
  1    0 [1, 3, 10, 14, 26, 45, 50, 66, 77, 77, 79, 84, 85]

对比两个例子中重复元素 77 的插入位置:

  • 用 insort_right() 时,第二个 77 插在位置 8(现有 77 的右边);
  • 用 insort_left() 时,第二个 77 插在位置 7(现有 77 的左边)。

根据实际需求选择即可,比如需要保持插入顺序的稳定性时,insort_left() 可能更合适。

总结一下

bisect 模块虽小,但在需要动态维护有序列表的场景中非常实用:

  1. 核心函数 bisect.bisect() 找位置,bisect.insort() 插元素;
  2. 处理重复元素时,用 insort_left() 插在左边,insort_right()(默认)插在右边;
  3. 数据量大、插入频繁时,比「插入后排序」效率高得多。

下次再遇到需要频繁插入并保持有序的需求,别再手动调用 sort 啦,试试 bisect 模块吧!

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

  • 发表于 2025-10-22 09:27
  • 阅读 ( 26 )
  • 分类:Python开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

1479 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 2228 文章
  3. Pack 1479 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章