UNPKG

@jcoreio/precise-bs

Version:

binary search and related utility functions

254 lines (243 loc) 11.8 kB
// eslint-disable-next-line @typescript-eslint/no-explicit-any export const DEFAULT_COMPARATOR = (a, b) => a < b ? -1 : a > b ? 1 : 0; export function binarySearch(array, find, comparator = DEFAULT_COMPARATOR, low = 0, high = array.length - 1) { let i, comparison; while (low <= high) { i = Math.floor((low + high) / 2); comparison = comparator(array[i], find); if (comparison < 0) { low = i + 1; continue; } if (comparison > 0) { high = i - 1; continue; } return i; } return low; } /** * Finds the index of the greatest element less than a given search value in a sorted array * using a binary search. If the given search value is less than or equal to all elements in the * array, returns -1. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function lowerIndex(array, find, comparator = DEFAULT_COMPARATOR, low, high) { return binarySearch(array, find, comparator, low, high) - 1; } /** * Finds the entry with the greatest element less than a given search value in a sorted array * using a binary search. If the search value is less than or equal to all elements in the * array, returns [-1, undefined]. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function lowerEntry(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const index = lowerIndex(array, find, comparator, low, high); return [index, array[index]]; } /** * Finds the greatest element less than a given value in a sorted array * using a binary search. If the given value is less than or equal to all elements in the * array, returns undefined. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function lowerValue(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const index = lowerIndex(array, find, comparator, low, high); return array[index]; } /** * Finds the index of the greatest element less than or equal to a given search value in a sorted array * using a binary search. If the given value is less than all elements in the * array, returns -1. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function floorIndex(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const i = binarySearch(array, find, comparator, low, high); return i === array.length || comparator(array[i], find) > 0 ? i - 1 : i; } /** * Finds the entry with the greatest element less than or equal to a given search value in a sorted array * using a binary search. If the given value is less than all elements in the * array, returns [-1, undefined]. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function floorEntry(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const index = floorIndex(array, find, comparator, low, high); return [index, array[index]]; } /** * Finds the greatest element less than or equal to a given search value in a sorted array * using a binary search. If the given value is less than all elements in the * array, returns undefined. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function floorValue(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const index = floorIndex(array, find, comparator, low, high); return array[index]; } /** * Finds the index of the least element greater than or equal to a given search value in a sorted array * using a binary search. If the given value is greater than all elements in the * array, returns the length of the array. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export const ceilingIndex = binarySearch; /** * Finds the entry with the least element greater than or equal to a given search value in a sorted array * using a binary search. If the given value is greater than all elements in the * array, returns [array.length, undefined]. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function ceilingEntry(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const index = ceilingIndex(array, find, comparator, low, high); return [index, array[index]]; } /** * Finds the least element greater than or equal to a given search value in a sorted array * using a binary search. If the given value is greater than all elements in the * array, returns undefined. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function ceilingValue(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const index = ceilingIndex(array, find, comparator, low, high); return array[index]; } /** * Finds the index of the least element greater than a given value in a sorted array * using a binary search. If the given value is greater than or equal to all elements in the * array, returns the length of the array. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function higherIndex(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const i = binarySearch(array, find, comparator, low, high); return i < array.length && comparator(array[i], find) <= 0 ? i + 1 : i; } /** * Finds the entry with the least element greater than a given value in a sorted array * using a binary search. If the given value is greater than or equal to all elements in the * array, returns [array.length, undefined]. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function higherEntry(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const index = higherIndex(array, find, comparator, low, high); return [index, array[index]]; } /** * Finds the least element greater than a given value in a sorted array * using a binary search. If the given value is greater than or equal to all elements in the * array, returns undefined. * * @param {array} the array to search in. * @param {find} the value to search for. * @param {comparator} two-argument function that returns &lt; 0 if * the first argument is less than the second; &gt; 0 if the first * argument is greater; and 0 otherwise. (defaults to <code>a - b</code>) * @param {low} the lower bound of the range in <code>array</code> to * search in (defaults to 0) * @param {high} the upper bound of the range in <code>array</code> to * search in (defaults to <code>array.length - 1</code>) */ export function higherValue(array, find, comparator = DEFAULT_COMPARATOR, low, high) { const index = higherIndex(array, find, comparator, low, high); return array[index]; }