-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathbinarySearch.js
More file actions
75 lines (71 loc) · 2.36 KB
/
binarySearch.js
File metadata and controls
75 lines (71 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
* Callback for finding distance for a collection item
*
* @callback funcDistance
* @param {Object} item A collection item
* @param {number} index An index of the collection item
* @returns {number} Returns a distance for the item
*/
/**
* @typedef {Object} BinarySearchResult
* @property {number} index The index of the nearest item in the collection
* @property {Object} item The nearest item
*/
/**
* Search sorted list of elements for the nearest item.
*
* @param {Object[]} items - The collection of elements.
* @param {funcDistance} callback - A callback function to get distance for the collection item.
* @param {number} [startMinimum=undefined] - The minimum index in the array to start search from
* @param {number} [startMaximum=undefined] - The maximum index in the array to start search from
* @returns {BinarySearchResult} Returns an item of the collection, which is nearest to optimal measured by callback function
*/
export default function binarySearch(items, callback, startMinimum, startMaximum) {
var result = null,
distance,
bestDistance,
minimum = startMinimum || 0,
maximum = startMaximum || (items.length - 1),
middle,
item;
if (items.length > 0) {
item = items[minimum];
result = { index: minimum, item: item };
distance = callback(item, minimum);
if (distance > 0) {
bestDistance = Math.abs(distance);
item = items[maximum];
distance = callback(item, maximum);
if (distance >= 0) {
result = { index: maximum, item: item };
} else {
distance = Math.abs(distance);
if (bestDistance > distance) {
bestDistance = distance;
result = { index: maximum, item: item };
}
while (minimum + 1 < maximum) {
middle = Math.round((minimum + maximum) / 2.0);
item = items[middle];
distance = callback(item, middle);
if (distance === 0) {
result = { index: middle, item: item };
break;
} else {
if (distance > 0) {
minimum = middle;
} else {
maximum = middle;
}
distance = Math.abs(distance);
if (bestDistance > distance) {
bestDistance = distance;
result = { index: middle, item: item };
}
}
}
}
}
}
return result;
};