@@ -21,7 +21,7 @@ example of the algorithm (the boundary conditions are already right!).
21
21
The following functions are provided:
22
22
23
23
24
- .. function :: bisect_left(a, x, lo=0, hi=len(a))
24
+ .. function :: bisect_left(a, x, lo=0, hi=len(a), *, key=None )
25
25
26
26
Locate the insertion point for *x * in *a * to maintain sorted order.
27
27
The parameters *lo * and *hi * may be used to specify a subset of the list
@@ -31,39 +31,106 @@ The following functions are provided:
31
31
parameter to ``list.insert() `` assuming that *a * is already sorted.
32
32
33
33
The returned insertion point *i * partitions the array *a * into two halves so
34
- that ``all(val < x for val in a[lo: i]) `` for the left side and
35
- ``all(val >= x for val in a[i: hi]) `` for the right side.
34
+ that ``all(val < x for val in a[lo : i]) `` for the left side and
35
+ ``all(val >= x for val in a[i : hi]) `` for the right side.
36
36
37
- .. function :: bisect_right(a, x, lo=0, hi=len(a))
37
+ *key * specifies a :term: `key function ` of one argument that is used to
38
+ extract a comparison key from each input element. The default value is
39
+ ``None `` (compare the elements directly).
40
+
41
+ .. versionchanged :: 3.10
42
+ Added the *key * parameter.
43
+
44
+
45
+ .. function :: bisect_right(a, x, lo=0, hi=len(a), *, key=None)
38
46
bisect(a, x, lo=0, hi=len(a))
39
47
40
48
Similar to :func: `bisect_left `, but returns an insertion point which comes
41
49
after (to the right of) any existing entries of *x * in *a *.
42
50
43
51
The returned insertion point *i * partitions the array *a * into two halves so
44
- that ``all(val <= x for val in a[lo:i]) `` for the left side and
45
- ``all(val > x for val in a[i:hi]) `` for the right side.
52
+ that ``all(val <= x for val in a[lo : i]) `` for the left side and
53
+ ``all(val > x for val in a[i : hi]) `` for the right side.
54
+
55
+ *key * specifies a :term: `key function ` of one argument that is used to
56
+ extract a comparison key from each input element. The default value is
57
+ ``None `` (compare the elements directly).
58
+
59
+ .. versionchanged :: 3.10
60
+ Added the *key * parameter.
61
+
46
62
47
- .. function :: insort_left(a, x, lo=0, hi=len(a))
63
+ .. function :: insort_left(a, x, lo=0, hi=len(a), *, key=None )
48
64
49
- Insert *x * in *a * in sorted order. This is equivalent to
50
- ``a.insert(bisect.bisect_left(a, x, lo, hi), x) `` assuming that *a * is
51
- already sorted. Keep in mind that the O(log n) search is dominated by
52
- the slow O(n) insertion step.
65
+ Insert *x * in *a * in sorted order.
53
66
54
- .. function :: insort_right(a, x, lo=0, hi=len(a))
67
+ *key * specifies a :term: `key function ` of one argument that is used to
68
+ extract a comparison key from each input element. The default value is
69
+ ``None `` (compare the elements directly).
70
+
71
+ This function first runs :func: `bisect_left ` to locate an insertion point.
72
+ Next, it runs the :meth: `insert ` method on *a * to insert *x * at the
73
+ appropriate position to maintain sort order.
74
+
75
+ Keep in mind that the ``O(log n) `` search is dominated by the slow O(n)
76
+ insertion step.
77
+
78
+ .. versionchanged :: 3.10
79
+ Added the *key * parameter.
80
+
81
+
82
+ .. function :: insort_right(a, x, lo=0, hi=len(a), *, key=None)
55
83
insort(a, x, lo=0, hi=len(a))
56
84
57
85
Similar to :func: `insort_left `, but inserting *x * in *a * after any existing
58
86
entries of *x *.
59
87
88
+ *key * specifies a :term: `key function ` of one argument that is used to
89
+ extract a comparison key from each input element. The default value is
90
+ ``None `` (compare the elements directly).
91
+
92
+ This function first runs :func: `bisect_right ` to locate an insertion point.
93
+ Next, it runs the :meth: `insert ` method on *a * to insert *x * at the
94
+ appropriate position to maintain sort order.
95
+
96
+ Keep in mind that the ``O(log n) `` search is dominated by the slow O(n)
97
+ insertion step.
98
+
99
+ .. versionchanged :: 3.10
100
+ Added the *key * parameter.
101
+
102
+
103
+ Performance Notes
104
+ -----------------
105
+
106
+ When writing time sensitive code using *bisect() * and *insort() *, keep these
107
+ thoughts in mind:
108
+
109
+ * Bisection is effective for searching ranges of values.
110
+ For locating specific values, dictionaries are more performant.
111
+
112
+ * The *insort() * functions are ``O(n) `` because the logarithmic search step
113
+ is dominated by the linear time insertion step.
114
+
115
+ * The search functions are stateless and discard key function results after
116
+ they are used. Consequently, if the search functions are used in a loop,
117
+ the key function may be called again and again on the same array elements.
118
+ If the key function isn't fast, consider wrapping it with
119
+ :func: `functools.cache ` to avoid duplicate computations. Alternatively,
120
+ consider searching an array of precomputed keys to locate the insertion
121
+ point (as shown in the examples section below).
122
+
60
123
.. seealso ::
61
124
62
- `SortedCollection recipe
63
- <https://code.activestate.com/recipes/577197-sortedcollection/> `_ that uses
64
- bisect to build a full-featured collection class with straight-forward search
65
- methods and support for a key-function. The keys are precomputed to save
66
- unnecessary calls to the key function during searches.
125
+ * `Sorted Collections
126
+ <http://www.grantjenks.com/docs/sortedcollections/> `_ is a high performance
127
+ module that uses *bisect * to managed sorted collections of data.
128
+
129
+ * The `SortedCollection recipe
130
+ <https://code.activestate.com/recipes/577197-sortedcollection/> `_ uses
131
+ bisect to build a full-featured collection class with straight-forward search
132
+ methods and support for a key-function. The keys are precomputed to save
133
+ unnecessary calls to the key function during searches.
67
134
68
135
69
136
Searching Sorted Lists
@@ -110,8 +177,8 @@ lists::
110
177
raise ValueError
111
178
112
179
113
- Other Examples
114
- --------------
180
+ Examples
181
+ --------
115
182
116
183
.. _bisect-example :
117
184
@@ -127,17 +194,12 @@ a 'B', and so on::
127
194
>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
128
195
['F', 'A', 'C', 'C', 'B', 'A', 'A']
129
196
130
- Unlike the :func: `sorted ` function, it does not make sense for the :func: `bisect `
131
- functions to have *key * or *reversed * arguments because that would lead to an
132
- inefficient design (successive calls to bisect functions would not "remember"
133
- all of the previous key lookups).
134
-
135
- Instead, it is better to search a list of precomputed keys to find the index
136
- of the record in question::
197
+ One technique to avoid repeated calls to a key function is to search a list of
198
+ precomputed keys to find the index of a record::
137
199
138
200
>>> data = [('red', 5), ('blue', 1), ('yellow', 8), ('black', 0)]
139
- >>> data.sort(key=lambda r: r[1])
140
- >>> keys = [r[1] for r in data] # precomputed list of keys
201
+ >>> data.sort(key=lambda r: r[1]) # Or use operator.itemgetter(1).
202
+ >>> keys = [r[1] for r in data] # Precompute a list of keys.
141
203
>>> data[bisect_left(keys, 0)]
142
204
('black', 0)
143
205
>>> data[bisect_left(keys, 1)]
0 commit comments