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 这类工具库价值的体现 ------ 让常见操作变得更简单、更高效。

相关推荐
步行cgn18 分钟前
在 HTML 表单中,name 和 value 属性在 GET 和 POST 请求中的对应关系如下:
前端·hive·html
hrrrrb25 分钟前
【Java Web 快速入门】十一、Spring Boot 原理
java·前端·spring boot
找不到工作的菜鸟33 分钟前
Three.js三大组件:场景(Scene)、相机(Camera)、渲染器(Renderer)
前端·javascript·html
定栓36 分钟前
vue3入门-v-model、ref和reactive讲解
前端·javascript·vue.js
专注API从业者41 分钟前
基于 Flink 的淘宝实时数据管道设计:商品详情流式处理与异构存储
大数据·前端·数据库·数据挖掘·flink
龙在天41 分钟前
H5开发,开发照相机,以及组件封装
前端
曼妥思1 小时前
PosterKit:跨框架海报生成工具
前端·开源
binqian1 小时前
【异步】js中异步的实现方式 async await /Promise / Generator
开发语言·前端·javascript
Jerry说前后端1 小时前
Android 移动端 UI 设计:前端常用设计原则总结
android·前端·ui
熊猫钓鱼1 小时前
基于Trae CN与TrendsHub快速实现的热点百事通
前端·trae