@@ -21,7 +21,7 @@ example of the algorithm (the boundary conditions are already right!).
2121The following functions are provided:
2222
2323
24- .. function :: bisect_left(a, x, lo=0, hi=len(a))
24+ .. function :: bisect_left(a, x, lo=0, hi=len(a), *, key=None )
2525
2626 Locate the insertion point for *x * in *a * to maintain sorted order.
2727 The parameters *lo * and *hi * may be used to specify a subset of the list
@@ -31,39 +31,106 @@ The following functions are provided:
3131 parameter to ``list.insert() `` assuming that *a * is already sorted.
3232
3333 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.
3636
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)
3846 bisect(a, x, lo=0, hi=len(a))
3947
4048 Similar to :func: `bisect_left `, but returns an insertion point which comes
4149 after (to the right of) any existing entries of *x * in *a *.
4250
4351 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+
4662
47- .. function :: insort_left(a, x, lo=0, hi=len(a))
63+ .. function :: insort_left(a, x, lo=0, hi=len(a), *, key=None )
4864
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.
5366
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)
5583 insort(a, x, lo=0, hi=len(a))
5684
5785 Similar to :func: `insort_left `, but inserting *x * in *a * after any existing
5886 entries of *x *.
5987
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+
60123.. seealso ::
61124
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.
67134
68135
69136Searching Sorted Lists
@@ -110,8 +177,8 @@ lists::
110177 raise ValueError
111178
112179
113- Other Examples
114- --------------
180+ Examples
181+ --------
115182
116183.. _bisect-example :
117184
@@ -127,17 +194,12 @@ a 'B', and so on::
127194 >>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
128195 ['F', 'A', 'C', 'C', 'B', 'A', 'A']
129196
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::
137199
138200 >>> 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.
141203 >>> data[bisect_left(keys, 0)]
142204 ('black', 0)
143205 >>> data[bisect_left(keys, 1)]
0 commit comments