_.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