_.sortedIndex(array, value)

36

_.sortedIndex(array, value)
_.sortedIndex用二分查找来查找到一个值应该在哪个索引插入数组后还能够保持数组的排序
参数

array (Array): 需要查找插入位置的数组
value (*): 需要插入的元素

返回值

(number): 返回元素应该插入的位置

例子

_.sortedIndex([30, 50], 40);
// => 1

源代码:

import baseSortedIndex from './.internal/baseSortedIndex.js'

/**
 * Uses a binary search to determine the lowest index at which `value`
 * should be inserted into `array` in order to maintain its sort order.
 *
 * @since 0.1.0
 * @category Array
 * @param {Array} array The sorted array to inspect.
 * @param {*} value The value to evaluate.
 * @returns {number} Returns the index at which `value` should be inserted
 *  into `array`.
 * @example
 *
 * sortedIndex([30, 50], 40)
 * // => 1
 */
//用二分查找来查找到一个值应该在哪个索引插入数组后还能够保持数组的排序
function sortedIndex(array, value) {
  return baseSortedIndex(array, value)//调用baseSortedIndex
}

export default sortedIndex
baseSortedIndex
import baseSortedIndexBy from './baseSortedIndexBy.js'
import isSymbol from '../isSymbol.js'

/** Used as references for the maximum length and index of an array. */
const MAX_ARRAY_LENGTH = 4294967295//最大数组长度
const HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1//最大数组长度的1/2

/**
 * The base implementation of `sortedIndex` and `sortedLastIndex` which
 * performs a binary search of `array` to determine the index at which `value`
 * should be inserted into `array` in order to maintain its sort order.
 *
 * @private
 * @param {Array} array The sorted array to inspect.
 * @param {*} value The value to evaluate.
 * @param {boolean} [retHighest] Specify returning the highest qualified index.
 * @returns {number} Returns the index at which `value` should be inserted
 *  into `array`.
 */
//sortedIndex和sortedLastIndex的基础实现
//array需要判断插入元素位置的数组,value需要插入的元素,retHighest是否返回高位的索引
function baseSortedIndex(array, value, retHighest) {
  let low = 0//数组起始索引,低位
  let high = array == null ? low : array.length//数组长度,高位

  if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
    //如果插入元素是number,并且不是NaN,并且数组长度小于数组最大长度的1/2
    while (low < high) {//低位小于高位的时候,循环
      //此处用二分法来查找最终的位置
      const mid = (low + high) >>> 1//数组的中间位置的索引
      const computed = array[mid]//中间位置的元素
      if (computed !== null && !isSymbol(computed) &&
          (retHighest ? (computed <= value) : (computed < value))) {
            //如果mid位置的元素不为null,并且不是symbol对象,并且mid元素小于要插入的元素
        low = mid + 1//低位等于中间位置加1的索引
      } else {//否则,区间的高位等于中间位置
        high = mid
      }
    }
    return high//返回最终找到的位置
  }
  return baseSortedIndexBy(array, value, (value) => value, retHighest)
  //如果不符合上面的判断条件,就调用baseSortedIndexBy来寻找
}

export default baseSortedIndex
baseSortedIndexBy
import isSymbol from '../isSymbol.js'

/** Used as references for the maximum length and index of an array. */
const MAX_ARRAY_LENGTH = 4294967295
const MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1

/**
 * The base implementation of `sortedIndexBy` and `sortedLastIndexBy`
 * which invokes `iteratee` for `value` and each element of `array` to compute
 * their sort ranking. The iteratee is invoked with one argument (value).
 *
 * @private
 * @param {Array} array The sorted array to inspect.
 * @param {*} value The value to evaluate.
 * @param {Function} iteratee The iteratee invoked per element.
 * @param {boolean} [retHighest] Specify returning the highest qualified index.
 * @returns {number} Returns the index at which `value` should be inserted
 *  into `array`.
 */
//sortedIndexBy和sortedLastIndexBy的基础实现
function baseSortedIndexBy(array, value, iteratee, retHighest) {
  value = iteratee(value)//用遍历器处理value

  let low = 0//区间低位
  let high = array == null ? 0 : array.length//区间高位
  const valIsNaN = value !== value//判断value是不是NaN
  const valIsNull = value === null//判断value是不是Null
  const valIsSymbol = isSymbol(value)//判断value是不是symbol对象
  const valIsUndefined = value === undefined//判断value是不是undefined

  while (low < high) {//循环查找,二分法
    let setLow//是否设置区间低位的标记
    const mid = Math.floor((low + high) / 2)//中间位置索引
    const computed = iteratee(array[mid])//遍历器处理中间位置的值
    const othIsDefined = computed !== undefined//判断computed是不是undefined
    const othIsNull = computed === null//判断computed是不是null
    const othIsReflexive = computed === computed//判断computed是不是NaN
    const othIsSymbol = isSymbol(computed)//判断computed是不是symbol对象

    if (valIsNaN) {
      //如果value是NaN
      //如果有retHighest,设置低位到中间;如果没有retHighest,computed不是NaN,设置低位到中间
      setLow = retHighest || othIsReflexive
    } else if (valIsUndefined) {
      //如果value是undefined
      //如果computed不是NaN,并且有retHithest或者computed不是undefined,设置低位到中间
      setLow = othIsReflexive && (retHighest || othIsDefined)
    } else if (valIsNull) {
      //如果value是null
      //如果computed不是NaN,并且computed不是undefined,并且  有retHighest或者computed不是null,设置低位到中间
      setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull)
    } else if (valIsSymbol) {
      //如果value是symbol对象
      //如果computed不是NaN,并且computed不是undefined,并且computed不是null,并且有retHighest或者computed不是symbol对象,设置低位到中间
      setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol)
    } else if (othIsNull || othIsSymbol) {
      //如果computed是null或者symbol对象,设置高位到中间
      setLow = false
    } else {//其他情况直接转换成数字比较大小
      setLow = retHighest ? (computed <= value) : (computed < value)
    }
    if (setLow) {//设置低位到中间
      low = mid + 1
    } else {//设置高位到中间
      high = mid
    }
  }
  return Math.min(high, MAX_ARRAY_INDEX)//返回找到的索引
}

export default baseSortedIndexBy

 

posted @ 2018-10-18 12:41  hahazexia  阅读(559)  评论(0)    收藏  举报