11"""Bisection algorithms."""
22
3- def insort_right (a , x , lo = 0 , hi = None ):
3+
4+ def insort_right (a , x , lo = 0 , hi = None , * , key = None ):
45 """Insert item x in list a, and keep it sorted assuming a is sorted.
56
67 If x is already in a, insert it to the right of the rightmost x.
78
89 Optional args lo (default 0) and hi (default len(a)) bound the
910 slice of a to be searched.
1011 """
11-
12- if lo < 0 :
13- raise ValueError ('lo must be non-negative' )
14- if hi is None :
15- hi = len (a )
16- while lo < hi :
17- mid = (lo + hi )// 2
18- if x < a [mid ]: hi = mid
19- else : lo = mid + 1
12+ if key is None :
13+ lo = bisect_right (a , x , lo , hi )
14+ else :
15+ lo = bisect_right (a , key (x ), lo , hi , key = key )
2016 a .insert (lo , x )
2117
22- def bisect_right (a , x , lo = 0 , hi = None ):
18+
19+ def bisect_right (a , x , lo = 0 , hi = None , * , key = None ):
2320 """Return the index where to insert item x in list a, assuming a is sorted.
2421
2522 The return value i is such that all e in a[:i] have e <= x, and all e in
26- a[i:] have e > x. So if x already appears in the list, a.insert(x) will
23+ a[i:] have e > x. So if x already appears in the list, a.insert(i, x) will
2724 insert just after the rightmost x already there.
2825
2926 Optional args lo (default 0) and hi (default len(a)) bound the
@@ -34,13 +31,26 @@ def bisect_right(a, x, lo=0, hi=None):
3431 raise ValueError ('lo must be non-negative' )
3532 if hi is None :
3633 hi = len (a )
37- while lo < hi :
38- mid = (lo + hi )// 2
39- if x < a [mid ]: hi = mid
40- else : lo = mid + 1
34+ # Note, the comparison uses "<" to match the
35+ # __lt__() logic in list.sort() and in heapq.
36+ if key is None :
37+ while lo < hi :
38+ mid = (lo + hi ) // 2
39+ if x < a [mid ]:
40+ hi = mid
41+ else :
42+ lo = mid + 1
43+ else :
44+ while lo < hi :
45+ mid = (lo + hi ) // 2
46+ if x < key (a [mid ]):
47+ hi = mid
48+ else :
49+ lo = mid + 1
4150 return lo
4251
43- def insort_left (a , x , lo = 0 , hi = None ):
52+
53+ def insort_left (a , x , lo = 0 , hi = None , * , key = None ):
4454 """Insert item x in list a, and keep it sorted assuming a is sorted.
4555
4656 If x is already in a, insert it to the left of the leftmost x.
@@ -49,22 +59,17 @@ def insort_left(a, x, lo=0, hi=None):
4959 slice of a to be searched.
5060 """
5161
52- if lo < 0 :
53- raise ValueError ('lo must be non-negative' )
54- if hi is None :
55- hi = len (a )
56- while lo < hi :
57- mid = (lo + hi )// 2
58- if a [mid ] < x : lo = mid + 1
59- else : hi = mid
62+ if key is None :
63+ lo = bisect_left (a , x , lo , hi )
64+ else :
65+ lo = bisect_left (a , key (x ), lo , hi , key = key )
6066 a .insert (lo , x )
6167
62-
63- def bisect_left (a , x , lo = 0 , hi = None ):
68+ def bisect_left (a , x , lo = 0 , hi = None , * , key = None ):
6469 """Return the index where to insert item x in list a, assuming a is sorted.
6570
6671 The return value i is such that all e in a[:i] have e < x, and all e in
67- a[i:] have e >= x. So if x already appears in the list, a.insert(x) will
72+ a[i:] have e >= x. So if x already appears in the list, a.insert(i, x) will
6873 insert just before the leftmost x already there.
6974
7075 Optional args lo (default 0) and hi (default len(a)) bound the
@@ -75,17 +80,31 @@ def bisect_left(a, x, lo=0, hi=None):
7580 raise ValueError ('lo must be non-negative' )
7681 if hi is None :
7782 hi = len (a )
78- while lo < hi :
79- mid = (lo + hi )// 2
80- if a [mid ] < x : lo = mid + 1
81- else : hi = mid
83+ # Note, the comparison uses "<" to match the
84+ # __lt__() logic in list.sort() and in heapq.
85+ if key is None :
86+ while lo < hi :
87+ mid = (lo + hi ) // 2
88+ if a [mid ] < x :
89+ lo = mid + 1
90+ else :
91+ hi = mid
92+ else :
93+ while lo < hi :
94+ mid = (lo + hi ) // 2
95+ if key (a [mid ]) < x :
96+ lo = mid + 1
97+ else :
98+ hi = mid
8299 return lo
83100
84- # Overwrite above definitions with a fast Rust implementation
101+
102+ # Overwrite above definitions with a fast C implementation
85103try :
86104 from _bisect import *
87105except ImportError :
88106 pass
89107
90- bisect = bisect_right # backward compatibility
91- insort = insort_right # backward compatibility
108+ # Create aliases
109+ bisect = bisect_right
110+ insort = insort_right
0 commit comments