Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 20933e0

Browse files
committed
Clean-up bisect docs.
* Document the post conditions for bisect_left() and bisect_right(). * Fix the grades example to use more obvious breakpoints and to use a list comprehension instead of map() which returns an iterator in Py3.x. * Improve and expand the examples of searching sorted lists. * Issue 4356 -- move up reference to the SortedCollection recipe.
1 parent 49203dc commit 20933e0

1 file changed

Lines changed: 62 additions & 60 deletions

File tree

Doc/library/bisect.rst

Lines changed: 62 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
.. module:: bisect
55
:synopsis: Array bisection algorithms for binary searching.
66
.. sectionauthor:: Fred L. Drake, Jr. <[email protected]>
7+
.. sectionauthor:: Raymond Hettinger <python at rcn.com>
78
.. example based on the PyModules FAQ entry by Aaron Watters <[email protected]>
89
910
This module provides support for maintaining a list in sorted order without
@@ -18,102 +19,109 @@ The following functions are provided:
1819

1920
.. function:: bisect_left(a, x, lo=0, hi=len(a))
2021

21-
Locate the proper insertion point for *x* in *a* to maintain sorted order.
22+
Locate the insertion point for *x* in *a* to maintain sorted order.
2223
The parameters *lo* and *hi* may be used to specify a subset of the list
2324
which should be considered; by default the entire list is used. If *x* is
2425
already present in *a*, the insertion point will be before (to the left of)
2526
any existing entries. The return value is suitable for use as the first
26-
parameter to ``list.insert()``. This assumes that *a* is already sorted.
27+
parameter to ``list.insert()`` assuming that *a* is already sorted.
2728

29+
The returned insertion point *i* partitions the array *a* into two halves so
30+
that ``all(val < x for val in a[lo:i])`` for the left side and
31+
``all(val >= x for val in a[i:hi])`` for the right side.
2832

2933
.. function:: bisect_right(a, x, lo=0, hi=len(a))
3034
bisect(a, x, lo=0, hi=len(a))
3135

3236
Similar to :func:`bisect_left`, but returns an insertion point which comes
3337
after (to the right of) any existing entries of *x* in *a*.
3438

39+
The returned insertion point *i* partitions the array *a* into two halves so
40+
that ``all(val <= x for val in a[lo:i])`` for the left side and
41+
``all(val > x for val in a[i:hi])`` for the right side.
3542

3643
.. function:: insort_left(a, x, lo=0, hi=len(a))
3744

3845
Insert *x* in *a* in sorted order. This is equivalent to
39-
``a.insert(bisect.bisect_left(a, x, lo, hi), x)``. This assumes that *a* is
40-
already sorted.
41-
42-
Also note that while the fast search step is O(log n), the slower insertion
43-
step is O(n), so the overall operation is slow.
44-
46+
``a.insert(bisect.bisect_left(a, x, lo, hi), x)`` assuming that *a* is
47+
already sorted. Keep in mind that the O(log n) search is dominated by
48+
the slow O(n) insertion step.
4549

4650
.. function:: insort_right(a, x, lo=0, hi=len(a))
4751
insort(a, x, lo=0, hi=len(a))
4852

4953
Similar to :func:`insort_left`, but inserting *x* in *a* after any existing
5054
entries of *x*.
5155

52-
Also note that while the fast search step is O(log n), the slower insertion
53-
step is O(n), so the overall operation is slow.
56+
.. seealso::
57+
58+
`SortedCollection recipe
59+
<http://code.activestate.com/recipes/577197-sortedcollection/>`_ that uses
60+
bisect to build a full-featured collection class with straight-forward search
61+
methods and support for a key-function. The keys are precomputed to save
62+
unnecessary calls to the key function during searches.
63+
5464

5565
Searching Sorted Lists
5666
----------------------
5767

58-
The above :func:`bisect` functions are useful for finding insertion points, but
59-
can be tricky or awkward to use for common searching tasks. The following three
68+
The above :func:`bisect` functions are useful for finding insertion points but
69+
can be tricky or awkward to use for common searching tasks. The following five
6070
functions show how to transform them into the standard lookups for sorted
6171
lists::
6272

63-
def find(a, key):
64-
'''Find leftmost item exact equal to the key.
65-
Raise ValueError if no such item exists.
66-
67-
'''
68-
i = bisect_left(a, key)
69-
if i < len(a) and a[i] == key:
73+
def index(a, x):
74+
'Locate the leftmost value exactly equal to x'
75+
i = bisect_left(a, x)
76+
if i != len(a) and a[i] == x:
77+
return i
78+
raise ValueError
79+
80+
def find_lt(a, x):
81+
'Find rightmost value less than x'
82+
i = bisect_left(a, x)
83+
if i:
84+
return a[i-1]
85+
raise ValueError
86+
87+
def find_le(a, x):
88+
'Find rightmost value less than or equal to x'
89+
i = bisect_right(a, x)
90+
if i:
91+
return a[i-1]
92+
raise ValueError
93+
94+
def find_gt(a, x):
95+
'Find leftmost value greater than x'
96+
i = bisect_right(a, x)
97+
if i != len(a):
7098
return a[i]
71-
raise ValueError('No item found with key equal to: %r' % (key,))
72-
73-
def find_le(a, key):
74-
'''Find largest item less-than or equal to key.
75-
Raise ValueError if no such item exists.
76-
If multiple keys are equal, return the leftmost.
99+
raise ValueError
77100

78-
'''
79-
i = bisect_left(a, key)
80-
if i < len(a) and a[i] == key:
101+
def find_ge(a, x):
102+
'Find leftmost item greater than or equal to x'
103+
i = bisect_left(a, x)
104+
if i != len(a):
81105
return a[i]
82-
if i == 0:
83-
raise ValueError('No item found with key at or below: %r' % (key,))
84-
return a[i-1]
85-
86-
def find_ge(a, key):
87-
'''Find smallest item greater-than or equal to key.
88-
Raise ValueError if no such item exists.
89-
If multiple keys are equal, return the leftmost.
106+
raise ValueError
90107

91-
'''
92-
i = bisect_left(a, key)
93-
if i == len(a):
94-
raise ValueError('No item found with key at or above: %r' % (key,))
95-
return a[i]
96108

97109
Other Examples
98110
--------------
99111

100112
.. _bisect-example:
101113

102-
The :func:`bisect` function is generally useful for categorizing numeric data.
103-
This example uses :func:`bisect` to look up a letter grade for an exam total
104-
(say) based on a set of ordered numeric breakpoints: 85 and up is an 'A', 75..84
105-
is a 'B', etc.
114+
The :func:`bisect` function can be useful for numeric table lookups. This
115+
example uses :func:`bisect` to look up a letter grade for an exam score (say)
116+
based on a set of ordered numeric breakpoints: 90 and up is an 'A', 80 to 89 is
117+
a 'B', and so on::
106118

107-
>>> grades = "FEDCBA"
108-
>>> breakpoints = [30, 44, 66, 75, 85]
109-
>>> from bisect import bisect
110-
>>> def grade(total):
111-
... return grades[bisect(breakpoints, total)]
119+
>>> def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
120+
... i = bisect(breakpoints, score)
121+
... return grades[i]
112122
...
113-
>>> grade(66)
114-
'C'
115-
>>> map(grade, [33, 99, 77, 44, 12, 88])
116-
['E', 'A', 'B', 'D', 'F', 'A']
123+
>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
124+
['F', 'A', 'C', 'C', 'B', 'A', 'A']
117125

118126
Unlike the :func:`sorted` function, it does not make sense for the :func:`bisect`
119127
functions to have *key* or *reversed* arguments because that would lead to an
@@ -135,9 +143,3 @@ of the record in question::
135143
>>> data[bisect_left(keys, 8)]
136144
('yellow', 8)
137145

138-
.. seealso::
139-
140-
`SortedCollection recipe
141-
<http://code.activestate.com/recipes/577197-sortedcollection/>`_ that
142-
encapsulates precomputed keys, allowing straight-forward insertion and
143-
searching using a *key* function.

0 commit comments

Comments
 (0)