Repository: chartjs/Chart.js
File: src/core/core.interaction.js (JavaScript)

Code before:
/**
 * Helper function to do binary search when possible
 * @param {object} metaset - the dataset meta
 * @param {string} axis - the axis mode. x|y|xy|r
 * @param {number} value - the value to find
 * @param {boolean} [intersect] - should the element intersect
 * @returns {{lo:number, hi:number}} indices to search data array between
 */
function binarySearch(metaset, axis, value, intersect) {
  const {controller, data, _sorted} = metaset;
  const iScale = controller._cachedMeta.iScale;
  const spanGaps = metaset.dataset ? metaset.dataset.options ? metaset.dataset.options.spanGaps : null : null;

  if (iScale && axis === iScale.axis && axis !== 'r' && _sorted && data.length) {
    const lookupMethod = iScale._reversePixels ? _rlookupByKey : _lookupByKey;
    if (!intersect) {
      const result = lookupMethod(data, axis, value);
      if (spanGaps) {
        const {vScale} = controller._cachedMeta;
        const {_parsed} = metaset;

        const distanceToDefinedLo = (_parsed
          .slice(0, result.lo + 1)
          .reverse()
          .findIndex(
            point => point[vScale.axis] || point[vScale.axis] === 0));
        result.lo -= Math.max(0, distanceToDefinedLo);

        const distanceToDefinedHi = (_parsed
          .slice(result.hi - 1)
          .findIndex(
            point => point[vScale.axis] || point[vScale.axis] === 0));
        result.hi += Math.max(0, distanceToDefinedHi);
      }
      return result;
    } else if (controller._sharedOptions) {
      // _sharedOptions indicates that each element has equal options -> equal proportions
      // So we can do a ranged binary search based on the range of first element and
      // be confident to get the full range of indices that can intersect with the value.
      const el = data[0];
      const range = typeof el.getRange === 'function' && el.getRange(axis);
      if (range) {
        const start = lookupMethod(data, axis, value - range);
        const end = lookupMethod(data, axis, value + range);
        return {lo: start.lo, hi: end.hi};
      }
    }
  }
  // Default to all elements, when binary search can not be used.
  return {lo: 0, hi: data.length - 1};
}

Review comment (performance):
thought: Could also use a helper. I'm not sure if it is any more readable or if there is an impact to performance in any direction.

```ts
            point => !isNullOrUndefined(point[vScale.axis])));
```

I'd also be tempted to just skipping nulls:

```ts
            point => point[vScale.axis] !== null));
```

I'm fine also with the current implementation :)

Code after:
/**
 * Helper function to do binary search when possible
 * @param {object} metaset - the dataset meta
 * @param {string} axis - the axis mode. x|y|xy|r
 * @param {number} value - the value to find
 * @param {boolean} [intersect] - should the element intersect
 * @returns {{lo:number, hi:number}} indices to search data array between
 */
function binarySearch(metaset, axis, value, intersect) {
  const {controller, data, _sorted} = metaset;
  const iScale = controller._cachedMeta.iScale;
  const spanGaps = metaset.dataset ? metaset.dataset.options ? metaset.dataset.options.spanGaps : null : null;

  if (iScale && axis === iScale.axis && axis !== 'r' && _sorted && data.length) {
    const lookupMethod = iScale._reversePixels ? _rlookupByKey : _lookupByKey;
    if (!intersect) {
      const result = lookupMethod(data, axis, value);
      if (spanGaps) {
        const {vScale} = controller._cachedMeta;
        const {_parsed} = metaset;

        const distanceToDefinedLo = (_parsed
          .slice(0, result.lo + 1)
          .reverse()
          .findIndex(
            point => !isNullOrUndef(point[vScale.axis])));
        result.lo -= Math.max(0, distanceToDefinedLo);

        const distanceToDefinedHi = (_parsed
          .slice(result.hi - 1)
          .findIndex(
            point => !isNullOrUndef(point[vScale.axis])));
        result.hi += Math.max(0, distanceToDefinedHi);
      }
      return result;
    } else if (controller._sharedOptions) {
      // _sharedOptions indicates that each element has equal options -> equal proportions
      // So we can do a ranged binary search based on the range of first element and
      // be confident to get the full range of indices that can intersect with the value.
      const el = data[0];
      const range = typeof el.getRange === 'function' && el.getRange(axis);
      if (range) {
        const start = lookupMethod(data, axis, value - range);
        const end = lookupMethod(data, axis, value + range);
        return {lo: start.lo, hi: end.hi};
      }
    }
  }
  // Default to all elements, when binary search can not be used.
  return {lo: 0, hi: data.length - 1};
}