bisect 模块包含两个主要函数,bisect 和 insort,两个函数都利用二分查找算法来在有序序列中查找或插入元素。

2.8.1 用bisect来搜索

bisect(haystack, needle) 在 haystack(干草垛)里搜索needle(针)的位置,该位置满足的条件是,把 needle 插入这个位置后,haystack 还能保持升序。也就是在说这个函数返回的位置前面的值,都小于或等于 needle 的值。其中 haystack 必须是一个有序的序列。你可以先用 bisect(haystack, needle) 查找位置 index,再用 haystack.insert(index, needle) 来插入新值。但你也可用insort 来一步到位,并且后者的速度更快一些。

示例 2-17 利用几个精心挑选的 needle,向我们展示了 bisect 返回的不同位置值。这段代码的输出结果显示在图 2-4 中。

示例 2-17 在有序序列中用 bisect 查找某个元素的插入位置

import bisect
import sys
HAYSTACK = [1, 4, 5, 6, 8, 12, 15, 20, 21, 23, 23, 26, 29, 30]
NEEDLES = [0, 1, 2, 5, 8, 10, 22, 23, 29, 30, 31]
ROW_FMT = '{0:2d} @ {1:2d} {2}{0:<2d}' def demo(bisect_fn):
for needle in reversed(NEEDLES):
position = bisect_fn(HAYSTACK, needle)
offset = position * ' |'
print(ROW_FMT.format(needle, position, offset)) if __name__ == '__main__':
if sys.argv[-1] == 'left':
bisect_fn = bisect.bisect_left
else:
bisect_fn = bisect.bisect print('DEMO:', bisect_fn.__name__)
print('haystack ->', ' '.join('%2d' % n for n in HAYSTACK))
demo(bisect_fn)

bisect 的表现可以从两个方面来调教:

首先可以用它的两个可选参数——lo 和 hi——来缩小搜寻的范围。lo的默认值是 0,hi 的默认值是序列的长度,即 len() 作用于该序列的返回值。

其次,bisect 函数其实是 bisect_right 函数的别名,后者还有个姊妹函数叫 bisect_left。它们的区别在于,bisect_left 返回的插入位置是原序列中跟被插入元素相等的元素的位置,也就是新元素会被放置于它相等的元素的前面,而 bisect_right 返回的则是跟它相等的元素之后的位置。这个细微的差别可能对于整数序列来讲没什么用,但是对于那些值相等但是形式不同的数据类型来讲,结果就不一样了。比如说虽然 1 == 1.0 的返回值是 True,1 和 1.0 其实是两个不同的元素。

2.8.2 用bisect.insort插入新元素

排序很耗时,因此在得到一个有序序列之后,我们最好能够保持它的有序。bisect.insort 就是为了这个而存在的。

insort(seq, item) 把变量 item 插入到序列 seq 中,并能保持 seq的升序顺序。详见示例 2-19 和它在图 2-6 里的输出。

  示例 2-19 insort 可以保持有序序列的顺序

import bisect
import random
SIZE=7 random.seed(1729)
my_list = []
for i in range(SIZE):
new_item = random.randrange(SIZE*2)
bisect.insort(my_list, new_item)
print('%2d ->' % new_item, my_list)

insort 跟 bisect 一样,有 lo 和 hi 两个可选参数用来控制查找的范围。它也有个变体叫 insort_left,这个变体在背后用的是bisect_left。

用bisect来管理已排序的序列的更多相关文章

  1. bisect维持已排序的序列

    如下: import bisect # 用来处理已排序的序列,用来维持已排序的序列,升序 # 基于二分查找 li = [] bisect.insort(li, 2) bisect.insort(li, ...

  2. bisect维护已排序的序列

    #!/usr/bin/env python # -*- coding:utf-8 -*- # author:love_cat import bisect # 用来处理已经排序好的序列,升序 # 二分查 ...

  3. 多线程更新已排序的Datagridview数据,造成数据错位

    多线程更新已排序的Datagridview数据,触发Datagridview的auto-sort时间,数据重新排序,造成后面更新数据的更新错误. 解决方法: 方法一.设置Datagridview的表头 ...

  4. Python判断列表是否已排序的各种方法及其性能分析

    目录 Python判断列表是否已排序的各种方法及其性能分析 声明 一. 问题提出 二. 代码实现 2.1 guess 2.2 sorted 2.3 for-loop 2.4 all 2.5 numpy ...

  5. [YY]已知逆序列求原序列(二分,树状数组)

    在看组合数学,看到逆序列这个概念.于是YY了一道题:已知逆序列,求出原序列. 例子: 元素个数 n = 8 逆序列 a={5,3,4,0,2,1,1,0} 则有原序列 p={4,8,6,2,5,1,3 ...

  6. 剑指Offer15 合并两个已排序链表

    /************************************************************************* > File Name: 15_MergeT ...

  7. 合并k个已排序的链表 分类: leetcode 算法 2015-07-09 17:43 3人阅读 评论(0) 收藏

    最先想到的是把两个linked lists 合并成一个. 这样从第一个开始一个一个吞并,直到所有list都被合并. class ListNode:# Definition for singly-lin ...

  8. C++版 - 剑指offer面试题38:数字在已排序数组中出现的次数

    数字在已排序数组中出现的次数 提交网址: http://www.nowcoder.com/practice/70610bf967994b22bb1c26f9ae901fa2?tpId=13&t ...

  9. STL基础--算法(已排序数据的算法,数值算法)

    已排序数据的算法 Binary search, merge, set operations 每个已排序数据算法都有一个同名的更一般的形式 vector vec = {8,9,9,9,45,87,90} ...

随机推荐

  1. docker pull 报错Get https://xxx.xxx.xxx.xxx:5000/v1/_ping: http: server gave HTTP response

    解决方法: vim /etc/docker/daemon.json { "insecure-registries":["xxx.xxx.xxx.xxx:5000" ...

  2. easyui-combobox和C标签判断回显

    <td width="40%"> <select class="easyui-combobox" id="work_property ...

  3. mysql索引分类

    mysql索引分类 一.总结 一句话总结: 主键索引:设定为主键后数据库会自动建立索引,innodb为聚簇索引 单值索引:一个索引只包含单个列,一个表可以有多个单列索引:CREATE INDEX id ...

  4. P2047 [NOI2007]社交网络(洛谷)

    题目描述 在社交网络 ( Social Network ) 的研究中,我们常常使用图论概念去解释一些社会现象.不妨看这样的一个问题:在一个社交圈子里有 nn 个人,人与人之间有不同程度的关系.我们将这 ...

  5. context_processor 上下文处理器

    context_processor 上下文处理器 博客里面有三个地方用到了标签云:主页面,分类页面,博客详情页面,于是有了下面一段代码 # 主页面 @main.route("/") ...

  6. Qt编写自定义控件36-图片浏览器

    一.前言 本控件主要用来作为一个简单的图片浏览器使用,可以上下翻页显示图片,图片还可以开启过度效果比如透明度渐变,应用场景有查看报警图片运行图片等.此控件非本人原创,来源于网络,我只是修正了好多处BU ...

  7. Qt编写安防视频监控系统7-全屏切换

    一.前言 全屏切换这个功能点属于简单的,一般会做到右键菜单中,也提供了快捷键比如alt+enter来触发,恢复全屏则按esc即可,全屏处理基本上都是隐藏通道面板以外的窗体,保持最大化展示,由于采用了模 ...

  8. kafka----简单的脚本命令重点

    kafka命令如下: kafka-shell基本命令 在节点hadoop-2,hadoop-3,hadoop-5,启动kafka 启动命令如下 kafka-server-start.sh /usr/l ...

  9. shell编程(2)

    一.变量简介 变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数据.脚本语言在定义变量时通常不需要指明类型,直接赋值即可,shell变量也遵循这个规则. 在Bash shell 中,每一个 ...

  10. 三种单点登录SSO的实现原理

    单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得 ...