示例 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 中可以这样设置,
那么输出的结果就变成了:
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.bisect
和 bisect.bisect_left
的区别,前者插入重复元素的位置是插入原来元素位置的右边,而后者则是插入原来的元素位置的左边。