bisect –維護有序列表
目的:不需要每次呼叫sort的方式維護有序列表。
bisect模組實現了一個演算法用於插入元素到有序列表。在一些情況下,這比反覆排序列表或構造一個大的列表再排序的效率更高。Bisect是二分法的意思,這裡使用二分法來排序,bisect的原始碼是二分法排序的樣板。這個模組的程式碼不到100行。
插入
import bisect import random # Use aconstant seed to ensure that # the samepseudo-random numbers # are usedeach time the loop is run. random.seed(1) print'New Pos Contents' print'--- --- --------' # Generaterandom numbers and # insert theminto a list in sorted # order. l = [] for i inrange(1, 15): #產生1-100的隨機數 r = random.randint(1, 100) position = bisect.bisect(l, r) bisect.insort(l, r) print'%3d %3d' % (r, position), l
執行結果:
#./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]
44 4[3, 10, 14, 26, 44, 45, 50, 66, 77, 79, 84, 85]
77 9[3, 10, 14, 26, 44, 45, 50, 66, 77, 77, 79, 84, 85]
1 0[1, 3, 10, 14, 26, 44, 45, 50, 66, 77, 77, 79, 84, 85]
Bisect模組提供的函式有:
bisect.bisect_left(a,x, lo=0, hi=len(a)) :
查詢在有序列表a中插入x的index。lo和hi用於指定列表的區間,預設是使用整個列表。如果x已經存在,在其左邊插入。返回值為index。
bisect.bisect_right(a,x, lo=0, hi=len(a))
bisect.bisect(a, x,lo=0, hi=len(a))
這2個和bisect_left類似,但如果x已經存在,在其右邊插入。
bisect.insort_left(a,x, lo=0, hi=len(a))
在有序列表a中插入x。和a.insert(bisect.bisect_left(a,x, lo, hi), x) 的效果相同。
bisect.insort_right(a,x, lo=0, hi=len(a))
bisect.insort(a, x,lo=0, hi=len(a))
和insort_left類似,但如果x已經存在,在其右邊插入。
可以函式可以分2類,bisect*,用於查詢index。Insort*用於實際插入。預設重複時從右邊插入。實際常用的估計是insort。
標準中有個根據分數計算出評級的例項:
>>> def grade(score,breakpoints=[60, 70, 80, 90], grades='FDCBA'):
... i = bisect(breakpoints, score)
... return grades[i]
...
>>> [grade(score)for score in [33, 99, 77, 70, 89, 90, 100]]
['F', 'A', 'C','C', 'B', 'A', 'A']
Bisect不像sort一樣支援關鍵字引數,建議如下處理:
>>> data =[('red', 5), ('blue', 1), ('yellow', 8), ('black', 0)] >>> data.sort(key=lambdar: r[1]) >>> keys =[r[1] for r in data] #precomputed list of keys >>> data[bisect_left(keys,0)] ('black', 0) >>> data[bisect_left(keys,1)] ('blue', 1) >>> data[bisect_left(keys,5)] ('red', 5) >>> data[bisect_left(keys,8)] ('yellow', 8)