Lodash源码阅读-sortedIndexOf

Lodash 源码阅读-sortedIndexOf

概述

sortedIndexOf 是 Lodash 里的一个查找函数,它在已排序的数组中查找某个值的位置。跟普通的 indexOf 比起来,它利用了数组已经排好序的特点,用二分查找的方式快速找到目标,速度比普通查找快很多(时间复杂度从 O(n) 降到 O(log n))。

前置学习

依赖函数

  • baseSortedIndex:内部的二分查找函数,用来找值应该插入的位置
  • eq:判断两个值是否相等的函数,能正确处理各种特殊情况(比如 NaN)

技术知识

  • 二分查找:一种在有序数据中快速查找的算法,每次把查找范围缩小一半
  • 相等性比较:JavaScript 中判断值相等的方法和陷阱
  • 边界检查:避免数组索引越界的常见技巧

源码实现

javascript 复制代码
/**
 * This method is like `_.indexOf` except that it performs a binary
 * search on a sorted `array`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Array
 * @param {Array} array The array to inspect.
 * @param {*} value The value to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 * @example
 *
 * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
 * // => 1
 */
function sortedIndexOf(array, value) {
  var length = array == null ? 0 : array.length;
  if (length) {
    var index = baseSortedIndex(array, value);
    if (index < length && eq(array[index], value)) {
      return index;
    }
  }
  return -1;
}

实现思路

sortedIndexOf 的思路很直接:

  1. 先检查数组是否为空,空的就直接返回 -1
  2. 用二分查找找到值应该在的位置(第一个大于等于这个值的位置)
  3. 检查一下这个位置上的值是否就是我们要找的值:
    • 是的话,返回这个位置
    • 不是的话,说明数组里没有这个值,返回 -1

这种方法比普通的从头找到尾的方式快多了,特别是在大数组中查找时。

源码解析

边界检查

javascript 复制代码
var length = array == null ? 0 : array.length;
if (length) {
  // 查找逻辑
}
return -1;

先看数组是否为空:

  • 如果传入的 arraynullundefined,就把长度设为 0
  • 只有数组有内容时才进行查找
  • 如果数组是空的,直接返回 -1

这个检查很重要,避免了访问不存在数组的属性而报错。

查找和匹配

javascript 复制代码
var index = baseSortedIndex(array, value);
if (index < length && eq(array[index], value)) {
  return index;
}

这部分是核心逻辑:

  1. baseSortedIndex 找到值应该在的位置
    • 这个函数使用二分查找,找到的是第一个大于等于目标值的位置
  2. 检查两个条件:
    • 找到的位置是否在数组范围内(index < length
    • 该位置的值是否等于要找的值(eq(array[index], value)
  3. 只有当这两个条件都满足时,才返回找到的位置

举个例子说明 index < length 的用处: 假设我们有数组 [1, 3, 5, 7],要查找值 9

  • baseSortedIndex 会返回 4(因为 9 应该插入到数组末尾)
  • 但数组长度只有 4,所以 index < length 条件不满足(4 < 4 为 false)
  • 这就避免了访问 array[4](不存在的元素),防止出现越界错误
  • 函数会直接返回 -1,表示没找到

这个检查确保了即使要查找的值比数组中所有元素都大,函数也能正确处理。

eq 函数比普通的 === 更智能,能正确处理 NaN 等特殊情况。

返回结果

javascript 复制代码
return -1;

如果没找到匹配的值,就返回 -1,这和 JavaScript 原生的 indexOf 行为一致。

总结

sortedIndexOf 这个小函数展示了数据结构和算法的重要性:

  1. 利用数据特性

    • 知道数组已排序后,可以用更高效的算法
    • 二分查找把时间复杂度从 O(n) 降到 O(log n)
  2. 健壮性设计

    • 做好边界检查和异常处理
    • eq 函数解决 JavaScript 相等比较的各种坑
  3. API 设计

    • 保持与原生 indexOf 相同的接口风格
    • 函数名清晰地表明它的用途和适用条件

这种专门针对特定场景优化的函数,是 Lodash 这类工具库价值的体现 ------ 让常见操作变得更简单、更高效。

相关推荐
Uyker41 分钟前
从零开始制作小程序简单概述
前端·微信小程序·小程序
Dontla4 小时前
为什么React列表项需要key?(React key)(稳定的唯一标识key有助于React虚拟DOM优化重绘大型列表)
javascript·react.js·ecmascript
EndingCoder5 小时前
React从基础入门到高级实战:React 实战项目 - 项目三:实时聊天应用
前端·react.js·架构·前端框架
阿阳微客6 小时前
Steam 搬砖项目深度拆解:从抵触到真香的转型之路
前端·笔记·学习·游戏
德育处主任Pro6 小时前
『React』Fragment的用法及简写形式
前端·javascript·react.js
CodeBlossom7 小时前
javaweb -html -CSS
前端·javascript·html
CodeCraft Studio7 小时前
【案例分享】如何借助JS UI组件库DHTMLX Suite构建高效物联网IIoT平台
javascript·物联网·ui
打小就很皮...7 小时前
HBuilder 发行Android(apk包)全流程指南
前端·javascript·微信小程序
集成显卡8 小时前
PlayWright | 初识微软出品的 WEB 应用自动化测试框架
前端·chrome·测试工具·microsoft·自动化·edge浏览器
前端小趴菜059 小时前
React - 组件通信
前端·react.js·前端框架