1 | // Generated by CoffeeScript 1.7.1
|
2 | (function() {
|
3 | var binary_interval_search;
|
4 |
|
5 | module.exports = binary_interval_search = function(data, lo_bound_key, hi_bound_key, id_key, probe) {
|
6 |
|
7 | /* Given `data`, three indexes, and a `probe`, perform a binary search through `data` to find into which
|
8 | of the given intervals `probe` falls.
|
9 |
|
10 | `data` must be a list of lists or objects with each entry representing an interval; intervals must not
|
11 | overlap, and the intervals in `data` must be sorted in ascending ordered. There may be gaps between
|
12 | intervals.
|
13 |
|
14 | You must give the keys to the lower and upper boundaries, so that `data[ idx ][ lo_bound_key ]` yields the
|
15 | first value and `data[ idx ][ hi_bound_key ]` the last value of each interval. `id_key` should be either
|
16 | `null` or a key for an entry so that `data[ idx ][ id_key ]` yields the ID (or whatever info) you want to
|
17 | retrieve with your search.
|
18 |
|
19 | If a match is found, the result will be either the index of the matching interval, or, if `id_key` was
|
20 | defined, `interval[ id_key ]`. If no match is found, `null` is returned.
|
21 |
|
22 | With thx to http://googleresearch.blogspot.de/2006/06/extra-extra-read-all-about-it-nearly.html
|
23 | */
|
24 | var hi_bound, hi_idx, id_and_range, lo_bound, lo_idx, mid_idx;
|
25 | lo_idx = 0;
|
26 | hi_idx = data.length - 1;
|
27 | while (lo_idx <= hi_idx) {
|
28 | mid_idx = Math.floor((lo_idx + hi_idx) / 2);
|
29 | id_and_range = data[mid_idx];
|
30 | lo_bound = id_and_range[lo_bound_key];
|
31 | hi_bound = id_and_range[hi_bound_key];
|
32 | if ((lo_bound <= probe && probe <= hi_bound)) {
|
33 | if (id_key != null) {
|
34 | return id_and_range[id_key];
|
35 | } else {
|
36 | return mid_idx;
|
37 | }
|
38 | }
|
39 | if (probe < lo_bound) {
|
40 | hi_idx = mid_idx - 1;
|
41 | } else {
|
42 | lo_idx = mid_idx + 1;
|
43 | }
|
44 | }
|
45 | return null;
|
46 | };
|
47 |
|
48 | }).call(this);
|