《流畅的 Python 》第 2 章笔记

示例 2-17

代码:

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)

① 最费解的就是这里,其实这里的 0,1,2,0 代表的是参数的 index,只是,0 号索引的元素被使用了 2 次!
② 这里的 needle 对应 ROW_RMT 中的 0,position 对应 1,offset 对应 2。

控制台打印的结果:

DEMO: bisect_right
haystack ->  1  4  5  6  8 12 15 20 21 23 23 26 29 30
31 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |31
30 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |30
29 @ 13      |  |  |  |  |  |  |  |  |  |  |  |  |29
23 @ 11      |  |  |  |  |  |  |  |  |  |  |23
22 @  9      |  |  |  |  |  |  |  |  |22
10 @  5      |  |  |  |  |10
 8 @  5      |  |  |  |  |8 
 5 @  3      |  |  |5 
 2 @  1      |2 
 1 @  1      |1 
 0 @  0    0

③ 这里也很巧妙,如果将控制台的参数多加一个 left,在 PyCharm 中可以这样设置,

20210216011802

那么输出的结果就变成了:

DEMO: bisect_left
haystack ->  1  4  5  6  8 12 15 20 21 23 23 26 29 30
31 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |31
30 @ 13      |  |  |  |  |  |  |  |  |  |  |  |  |30
29 @ 12      |  |  |  |  |  |  |  |  |  |  |  |29
23 @  9      |  |  |  |  |  |  |  |  |23
22 @  9      |  |  |  |  |  |  |  |  |22
10 @  5      |  |  |  |  |10
 8 @  4      |  |  |  |8 
 5 @  2      |  |5 
 2 @  1      |2 
 1 @  0    1 
 0 @  0    0 

这反映的其实是 bisect.bisectbisect.bisect_left 的区别,前者插入重复元素的位置是插入原来元素位置的右边,而后者则是插入原来的元素位置的左边。

posted @ 2021-02-16 01:22  模糊计算士  阅读(70)  评论(0编辑  收藏  举报