Skip to content

Instantly share code, notes, and snippets.

@kylebgorman
Created December 6, 2011 01:48
Show Gist options
  • Save kylebgorman/1436322 to your computer and use it in GitHub Desktop.
Save kylebgorman/1436322 to your computer and use it in GitHub Desktop.
I constantly use these Python patterns for searching sorted iterables of continuous points
#!/usr/bin/env python
# point_bisect.py
# Kyle Gorman
#
# I continually use these two patterns in Python for iterables that contain
# continuous values, sorted. Here they are in their full glory.
from bisect import bisect_left
def nearest(query, sequence):
"""
Return the value in sequence, an sorted object indexed by integer/slice
keys, which is nearest to the query
>>> sequence = [.2, .3, .8]
>>> print nearest(.1, sequence)
0.2
>>> print nearest(.2, sequence)
0.2
>>> print nearest(.3, sequence)
0.3
>>> print nearest(.4, sequence)
0.3
>>> print nearest(.7, sequence)
0.8
>>> print nearest(1., sequence)
0.8
"""
i = bisect_left(sequence, query)
if i == 0: return sequence[0]
elif i == len(sequence): return sequence[-1]
elif sequence[i] - query > query - sequence[i - 1]: return sequence[i - 1]
else: return sequence[i]
def within(query, sequence, offset):
"""
Return True if there is some numeric element within the sequence which is
within offset of query, or return False otherwise
>>> sequence = [.2, .3, .8]
>>> print within(0., sequence, .1)
False
>>> print within(.1, sequence, .2)
True
>>> print within(.2, sequence, .1)
True
>>> print within(.9, sequence, .1)
True
>>> print within(1., sequence, .1)
False
"""
i = bisect_left(sequence, query)
if i == 0: return sequence[0] - query <= offset
elif i == len(sequence): return query - sequence[-1] <= offset
elif sequence[i] - query <= offset: return True
elif query - sequence[i - 1] <= offset: return True
else: return False
if __name__ == '__main__':
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment