blob: 2bee02f7922a94aab864629a1df12ac76a35c7a2 [file] [log] [blame]
Georg Brandl8ec7f652007-08-15 14:28:01 +00001:mod:`bisect` --- Array bisection algorithm
2===========================================
3
4.. module:: bisect
5 :synopsis: Array bisection algorithms for binary searching.
6.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
Raymond Hettinger54f824f2010-09-01 19:42:36 +00007.. sectionauthor:: Raymond Hettinger <python at rcn.com>
Georg Brandlb19be572007-12-29 10:57:00 +00008.. example based on the PyModules FAQ entry by Aaron Watters <arw@pythonpros.com>
Georg Brandl8ec7f652007-08-15 14:28:01 +00009
10This module provides support for maintaining a list in sorted order without
11having to sort the list after each insertion. For long lists of items with
12expensive comparison operations, this can be an improvement over the more common
13approach. The module is called :mod:`bisect` because it uses a basic bisection
14algorithm to do its work. The source code may be most useful as a working
15example of the algorithm (the boundary conditions are already right!).
16
Raymond Hettinger47ed1c12010-08-07 21:55:06 +000017.. versionadded:: 2.1
18
Georg Brandl8ec7f652007-08-15 14:28:01 +000019The following functions are provided:
20
21
Raymond Hettinger54f824f2010-09-01 19:42:36 +000022.. function:: bisect_left(a, x, lo=0, hi=len(a))
Georg Brandl8ec7f652007-08-15 14:28:01 +000023
Raymond Hettinger54f824f2010-09-01 19:42:36 +000024 Locate the insertion point for *x* in *a* to maintain sorted order.
25 The parameters *lo* and *hi* may be used to specify a subset of the list
26 which should be considered; by default the entire list is used. If *x* is
27 already present in *a*, the insertion point will be before (to the left of)
28 any existing entries. The return value is suitable for use as the first
29 parameter to ``list.insert()`` assuming that *a* is already sorted.
Georg Brandl8ec7f652007-08-15 14:28:01 +000030
Raymond Hettinger54f824f2010-09-01 19:42:36 +000031 The returned insertion point *i* partitions the array *a* into two halves so
32 that ``all(val < x for val in a[lo:i])`` for the left side and
33 ``all(val >= x for val in a[i:hi])`` for the right side.
Georg Brandl8ec7f652007-08-15 14:28:01 +000034
Raymond Hettinger54f824f2010-09-01 19:42:36 +000035.. function:: bisect_right(a, x, lo=0, hi=len(a))
36 bisect(a, x, lo=0, hi=len(a))
Georg Brandl8ec7f652007-08-15 14:28:01 +000037
Raymond Hettinger54f824f2010-09-01 19:42:36 +000038 Similar to :func:`bisect_left`, but returns an insertion point which comes
39 after (to the right of) any existing entries of *x* in *a*.
Georg Brandl8ec7f652007-08-15 14:28:01 +000040
Raymond Hettinger54f824f2010-09-01 19:42:36 +000041 The returned insertion point *i* partitions the array *a* into two halves so
42 that ``all(val <= x for val in a[lo:i])`` for the left side and
43 ``all(val > x for val in a[i:hi])`` for the right side.
Georg Brandl8ec7f652007-08-15 14:28:01 +000044
Raymond Hettinger54f824f2010-09-01 19:42:36 +000045.. function:: insort_left(a, x, lo=0, hi=len(a))
Georg Brandl8ec7f652007-08-15 14:28:01 +000046
Raymond Hettinger54f824f2010-09-01 19:42:36 +000047 Insert *x* in *a* in sorted order. This is equivalent to
48 ``a.insert(bisect.bisect_left(a, x, lo, hi), x)`` assuming that *a* is
49 already sorted. Keep in mind that the O(log n) search is dominated by
50 the slow O(n) insertion step.
Georg Brandl8ec7f652007-08-15 14:28:01 +000051
Raymond Hettinger54f824f2010-09-01 19:42:36 +000052.. function:: insort_right(a, x, lo=0, hi=len(a))
Raymond Hettinger47ed1c12010-08-07 21:55:06 +000053 insort(a, x, lo=0, hi=len(a))
Georg Brandl8ec7f652007-08-15 14:28:01 +000054
Raymond Hettinger54f824f2010-09-01 19:42:36 +000055 Similar to :func:`insort_left`, but inserting *x* in *a* after any existing
56 entries of *x*.
Georg Brandl8ec7f652007-08-15 14:28:01 +000057
Raymond Hettinger54f824f2010-09-01 19:42:36 +000058.. seealso::
59
60 `SortedCollection recipe
61 <http://code.activestate.com/recipes/577197-sortedcollection/>`_ that uses
62 bisect to build a full-featured collection class with straight-forward search
63 methods and support for a key-function. The keys are precomputed to save
64 unnecessary calls to the key function during searches.
65
Georg Brandl8ec7f652007-08-15 14:28:01 +000066
Raymond Hettinger47ed1c12010-08-07 21:55:06 +000067Searching Sorted Lists
68----------------------
Georg Brandl8ec7f652007-08-15 14:28:01 +000069
Raymond Hettinger54f824f2010-09-01 19:42:36 +000070The above :func:`bisect` functions are useful for finding insertion points but
71can be tricky or awkward to use for common searching tasks. The following five
Raymond Hettinger47ed1c12010-08-07 21:55:06 +000072functions show how to transform them into the standard lookups for sorted
73lists::
Georg Brandl8ec7f652007-08-15 14:28:01 +000074
Raymond Hettinger54f824f2010-09-01 19:42:36 +000075 def index(a, x):
76 'Locate the leftmost value exactly equal to x'
77 i = bisect_left(a, x)
78 if i != len(a) and a[i] == x:
79 return i
80 raise ValueError
Georg Brandl8ec7f652007-08-15 14:28:01 +000081
Raymond Hettinger54f824f2010-09-01 19:42:36 +000082 def find_lt(a, x):
83 'Find rightmost value less than x'
84 i = bisect_left(a, x)
85 if i:
86 return a[i-1]
87 raise ValueError
88
89 def find_le(a, x):
90 'Find rightmost value less than or equal to x'
91 i = bisect_right(a, x)
92 if i:
93 return a[i-1]
94 raise ValueError
95
96 def find_gt(a, x):
97 'Find leftmost value greater than x'
98 i = bisect_right(a, x)
99 if i != len(a):
Raymond Hettinger47ed1c12010-08-07 21:55:06 +0000100 return a[i]
Raymond Hettinger54f824f2010-09-01 19:42:36 +0000101 raise ValueError
Georg Brandl8ec7f652007-08-15 14:28:01 +0000102
Raymond Hettinger54f824f2010-09-01 19:42:36 +0000103 def find_ge(a, x):
104 'Find leftmost item greater than or equal to x'
105 i = bisect_left(a, x)
106 if i != len(a):
Raymond Hettinger47ed1c12010-08-07 21:55:06 +0000107 return a[i]
Raymond Hettinger54f824f2010-09-01 19:42:36 +0000108 raise ValueError
Raymond Hettinger47ed1c12010-08-07 21:55:06 +0000109
Raymond Hettinger47ed1c12010-08-07 21:55:06 +0000110
111Other Examples
112--------------
Georg Brandl8ec7f652007-08-15 14:28:01 +0000113
114.. _bisect-example:
115
Raymond Hettinger54f824f2010-09-01 19:42:36 +0000116The :func:`bisect` function can be useful for numeric table lookups. This
117example uses :func:`bisect` to look up a letter grade for an exam score (say)
118based on a set of ordered numeric breakpoints: 90 and up is an 'A', 80 to 89 is
119a 'B', and so on::
Georg Brandl8ec7f652007-08-15 14:28:01 +0000120
Raymond Hettinger54f824f2010-09-01 19:42:36 +0000121 >>> def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
122 ... i = bisect(breakpoints, score)
123 ... return grades[i]
Georg Brandl8ec7f652007-08-15 14:28:01 +0000124 ...
Raymond Hettinger54f824f2010-09-01 19:42:36 +0000125 >>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
126 ['F', 'A', 'C', 'C', 'B', 'A', 'A']
Georg Brandl8ec7f652007-08-15 14:28:01 +0000127
Raymond Hettinger87be88c2009-06-11 22:04:00 +0000128Unlike the :func:`sorted` function, it does not make sense for the :func:`bisect`
129functions to have *key* or *reversed* arguments because that would lead to an
130inefficent design (successive calls to bisect functions would not "remember"
131all of the previous key lookups).
Georg Brandl8ec7f652007-08-15 14:28:01 +0000132
Raymond Hettinger87be88c2009-06-11 22:04:00 +0000133Instead, it is better to search a list of precomputed keys to find the index
134of the record in question::
135
136 >>> data = [('red', 5), ('blue', 1), ('yellow', 8), ('black', 0)]
Raymond Hettinger2742e7e2009-06-11 22:08:10 +0000137 >>> data.sort(key=lambda r: r[1])
138 >>> keys = [r[1] for r in data] # precomputed list of keys
Raymond Hettinger87be88c2009-06-11 22:04:00 +0000139 >>> data[bisect_left(keys, 0)]
140 ('black', 0)
141 >>> data[bisect_left(keys, 1)]
142 ('blue', 1)
143 >>> data[bisect_left(keys, 5)]
144 ('red', 5)
145 >>> data[bisect_left(keys, 8)]
146 ('yellow', 8)
Raymond Hettinger47ed1c12010-08-07 21:55:06 +0000147