UNPKG

2.95 kBJavaScriptView Raw
1export function minMax (arr) {
2 var len = arr.length
3 var min = Infinity
4 var max = -Infinity
5 while (len--) {
6 var el = arr[len]
7 if (el == null) {
8 // do nothing
9 } else if (el < min) {
10 min = el
11 } else if (el > max) {
12 max = el
13 }
14 }
15 if (min === Infinity) {
16 min = max
17 } else if (max === -Infinity) {
18 max = min
19 }
20 if (min === Infinity || min === -Infinity) {
21 // all values were null
22 min = null
23 max = null
24 }
25 return [min, max]
26}
27
28/**
29 * Return the indices of the two neighbors in the sorted array closest to the given number.
30 *
31 * @example
32 * var a = [2,5,8,12,13]
33 * var i = CovUtils.indicesOfNearest(a, 6)
34 * // i == [1,2]
35 * var j = CovUtils.indicesOfNearest(a, 5)
36 * // j == [1,1]
37 * var k = CovUtils.indicesOfNearest(a, 50)
38 * // k == [4,4]
39 *
40 * @param {Array<number>} a The array to search through. Must be sorted, ascending or descending.
41 * @param {number} x The target number.
42 * @return {[lo,hi]} The indices of the two closest values, may be equal.
43 * If `x` exists in the array, both neighbors point to `x`.
44 * If `x` is lower (greater if descending) than the first value, both neighbors point to 0.
45 * If `x` is greater (lower if descending) than the last value, both neighbors point to the last index.
46 */
47export function indicesOfNearest (a, x) {
48 if (a.length === 0) {
49 throw new Error('Array must have at least one element')
50 }
51 var lo = -1
52 var hi = a.length
53 const ascending = a.length === 1 || a[0] < a[1]
54 // we have two separate code paths to help the runtime optimize the loop
55 if (ascending) {
56 while (hi - lo > 1) {
57 let mid = Math.round((lo + hi) / 2)
58 if (a[mid] <= x) {
59 lo = mid
60 } else {
61 hi = mid
62 }
63 }
64 } else {
65 while (hi - lo > 1) {
66 let mid = Math.round((lo + hi) / 2)
67 if (a[mid] >= x) { // here's the difference
68 lo = mid
69 } else {
70 hi = mid
71 }
72 }
73 }
74 if (a[lo] === x) hi = lo
75 if (lo === -1) lo = hi
76 if (hi === a.length) hi = lo
77 return [lo, hi]
78}
79
80/**
81 * Return the index of the value closest to the given number in a sorted array.
82 *
83 * @example
84 * var a = [2,5,8,12,13]
85 * var i = CovUtils.indexOfNearest(a, 6)
86 * // i == 1
87 * var j = CovUtils.indexOfNearest(a, 7)
88 * // j == 2
89 * var k = CovUtils.indexOfNearest(a, 50)
90 * // k == 4
91 *
92 * @param {Array<number>} a The array to search through. Must be sorted, ascending or descending.
93 * @param {number} x The target number.
94 * @return {number} The array index whose value is closest to `x`.
95 * If `x` happens to be exactly between two values, then the lower index is returned.
96 */
97export function indexOfNearest (a, x) {
98 var i = indicesOfNearest(a, x)
99 var lo = i[0]
100 var hi = i[1]
101 if (Math.abs(x - a[lo]) <= Math.abs(x - a[hi])) {
102 return lo
103 } else {
104 return hi
105 }
106}