Skip to content

feat(nearest): add IntervalTree.nearest() - #161

Open
SahilRajputdotexe wants to merge 1 commit into
chaimleib:masterfrom
SahilRajputdotexe:feat/nearest-queries
Open

SahilRajputdotexe wants to merge 1 commit into
chaimleib:masterfrom
SahilRajputdotexe:feat/nearest-queries

Conversation

@SahilRajputdotexe

Copy link
Copy Markdown

This adds IntervalTree.nearest(target, k=None), which finds the interval closest to a point or an Interval. Closes #114.

With k=None it returns one Interval, or None if the tree is empty. With an integer k it returns a list of up to k intervals, nearest first. Distance is the existing Interval.distance_to(): 0 when the two overlap or touch, otherwise the size of the gap. Ties are broken by the normal Interval ordering, so the result is stable even when the data fields can't be compared with each other.

>>> t = IntervalTree.from_tuples([(0, 5, 'a'), (10, 15, 'b'), (30, 40, 'c')])
>>> t.nearest(8)
Interval(10, 15, 'b')
>>> t.nearest(Interval(20, 22), k=2)
[Interval(10, 15, 'b'), Interval(30, 40, 'c')]

It doesn't scan the whole tree. It looks at a window around the target, using the boundary table to include intervals exactly at the window's edge, and doubles the window until it holds k intervals. A null Interval target raises ValueError, a negative k raises ValueError, and a non-integer k raises TypeError.

I added tests in test/intervaltree_methods/nearest_test.py, including a randomized comparison against a brute-force sort, plus README and CHANGELOG entries. The suite passes locally on Python 3.9, 3.12 and 3.14, and the full CI matrix (2.7, 3.5 to 3.14, flake8) passes on my fork.

I kept this to nearest only. A custom distance callable, a "within distance" query and cross-tree joins could be built on top of it if you want them, but I didn't want to widen the API in one PR.

Returns the interval closest to a point or Interval, or a list of the k
closest, using the same gap as Interval.distance_to(). Ties are broken by
interval order. The search widens a window around the target using the
boundary table instead of scanning every interval.

Refs chaimleib#114
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for finding the nearest interval.

1 participant