_.intersection([arrays])


21

_.intersection([arrays])
_.intersection取数组的交集,结果的次序和引用取决于第一个数组
参数

array (Array): 需要取交集的数组组成的数组

返回值

(Array):返回交集元素组成的新数组

例子

_.intersection([2, 1], [2, 3]);
// => [2]

源代码:

下面只注释核心实现,其他用到的方法之前difference的时候都看过了

import map from './map.js'
import baseIntersection from './.internal/baseIntersection.js'
import castArrayLikeObject from './.internal/castArrayLikeObject.js'

/**
 * Creates an array of unique values that are included in all given arrays
 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * for equality comparisons. The order and references of result values are
 * determined by the first array.
 *
 * @since 0.1.0
 * @category Array
 * @param {...Array} [arrays] The arrays to inspect.
 * @returns {Array} Returns the new array of intersecting values.
 * @example
 *
 * intersection([2, 1], [2, 3])
 * // => [2]
 */
//intersection取数组的交集,结果的次序和引用取决于第一个参数数组
//使用sameValueZero规则来判断元素是否相等
function intersection(...arrays) {
  const mapped = map(arrays, castArrayLikeObject)//循环参数数组,将不是array-like对象的参数都转变成空数组
  return (mapped.length && mapped[0] === arrays[0])
    ? baseIntersection(mapped)
    : []
    //如果参数数组长度不为0,且第一个参数数组是array-like对象,就调用baseIntersection处理
    //否则,返回空数组
}

export default intersection

下面是baseIntersection

import SetCache from './SetCache.js'
import arrayIncludes from './arrayIncludes.js'//判断数组是否包含给定值
import arrayIncludesWith from './arrayIncludesWith.js'//类似于数组的includes方法,区别是它的comparator需要作为参数传入
import map from '../map.js'
import cacheHas from './cacheHas.js'

/**
 * The base implementation of methods like `intersection` that accepts an
 * array of arrays to inspect.
 *
 * @private
 * @param {Array} arrays The arrays to inspect.
 * @param {Function} [iteratee] The iteratee invoked per element.
 * @param {Function} [comparator] The comparator invoked per element.
 * @returns {Array} Returns the new array of shared values.
 */
//取数组交集方法intersection的基础实现
//arrays需要取交集的数组组成的数组,iteratee循环时每个元素调用的迭代器,comparator比较器
function baseIntersection(arrays, iteratee, comparator) {
  const includes = comparator ? arrayIncludesWith : arrayIncludes
  //判断数组是否包含给定值
  const length = arrays[0].length//第一个数组的长度
  const othLength = arrays.length//所有需要比较的数组有多少个
  const caches = new Array(othLength)//创建一个和需要比较的数组的数量一样长度的数组来做缓存
  const result = []//结果数组

  let array
  let maxLength = Infinity
  let othIndex = othLength//循环arrays的索引

  while (othIndex--) {
    array = arrays[othIndex]//当前数组
    if (othIndex && iteratee) {//如果传递了迭代器参数,就循环当前数组为其中每个元素执行迭代器
      array = map(array, (value) => iteratee(value))
    }
    maxLength = Math.min(array.length, maxLength)//array.length和Infinity中取一个小值,要获取到一个结果数组的最大长度后面有用
    caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
      ? new SetCache(othIndex && array)
      : undefined
      //缓存数组处理
      //如果没有comparator,并且有iteratee或者第一个数组和当前循环到的数组的长度大于等于120,就开启缓存
      //开启缓存的时候,caches[othIndex],caches的当前值赋值为一个SetCache对象,传递当前循环到的数组作为参数
      //不开启缓存,就存一个undefined
  }
  array = arrays[0]//第一个数组,用于取交集的次序的根据

  let index = -1//循环索引
  const seen = caches[0]//缓存的第一个数组

  outer://标签语句,循环跳出时会跳到这里
  while (++index < length && result.length < maxLength) {
    //循环第一个数组,第二个条件是结果数组的长度不能超过最大长度
    let value = array[index]//第一个数组的当前循环元素
    const computed = iteratee ? iteratee(value) : value//用迭代器处理一下第一个数组的当前元素

    value = (comparator || value !== 0) ? value : 0//处理value为0的情况,因为可能还有+0,-0之类的元素值
    if (!(seen
          ? cacheHas(seen, computed)
          : includes(result, computed, comparator)
        )) {//如果有第一个数组的缓存,就用cacheHas来判断缓存里是否有computed;如果没有缓存,就用includes判断result数组里是否有computed。如果没有找到,就执行下面操作
      othIndex = othLength//需要比较的数组长度,作为循环索引
      while (--othIndex) {//循环需要比较的数组
        const cache = caches[othIndex]//当前循环到的数组的缓存
        if (!(cache
              ? cacheHas(cache, computed)
              : includes(arrays[othIndex], computed, comparator))
            ) {//有缓存就用cacheHas判断是否有当前元素;如果没有缓存就用includes判断
          continue outer//如果有一个数组里没有当前computed,就跳过,直接循环下一个第一个数组的元素
        }
      }
      //否则说明每一个数组里都有当前computed,就push到seen里和result里
      if (seen) {
        seen.push(computed)
      }
      result.push(value)
    }
  }
  return result
}

export default baseIntersection

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM