每天一個lodash方法(7)

Array method 系列之七 —— intersection
intersectiondifference是功能相反的兩個方法。
difference是拋出數(shù)組中相同的部分,留下不同的部分,即取補集。
intersection是留下相同的部分,即取交集。

intersection系列包含三個方法:intersection、intersectionByintersectionWith。
difference系列相似,intersection提供多個數(shù)組的基礎比較取交集。
intersectionBy利用iteratee方法對數(shù)組元素進行預先處理。
intersectionWith利用comparator比較器自定義比較方法。

但是三種方法的思路很相似。

  1. 對參數(shù)進行預處理。得到array,comparatoriteratee。
  2. 執(zhí)行baseIntersection方法
    • 根據(jù)數(shù)組長度判斷是否緩存。緩存源碼此處略過。
    • 雙重遍歷:判斷第一個數(shù)組的每個元素是否包含在其余數(shù)組中。
  3. 結(jié)果返回。

以下是源碼。

// intersection.js
// 注意此處傳參是...arrays
function intersection(...arrays) {
  // 參數(shù)處理
  const mapped = map(arrays, castArrayLikeObject)
  // 執(zhí)行核心方法
  return (mapped.length && mapped[0] === arrays[0])
    ? baseIntersection(mapped)
    : []
}

// intersectionBy.js
function intersectionBy(...arrays) {
  let iteratee = last(arrays)
  const mapped = map(arrays, castArrayLikeObject)

  if (iteratee === last(mapped)) {
    iteratee = undefined
  } else {
    mapped.pop()
  }
  // 以上為參數(shù)處理,分離得到數(shù)組和迭代器
  return (mapped.length && mapped[0] === arrays[0])
    ? baseIntersection(mapped, iteratee)
    : []
}

// intersectionWith.js
function intersectionWith(...arrays) {
  let comparator = last(arrays)
  const mapped = map(arrays, castArrayLikeObject)

  comparator = typeof comparator == 'function' ? comparator : undefined
  if (comparator) {
    mapped.pop()
  }
  // 以上為參數(shù)處理,分離得到數(shù)組和比較器 
  return (mapped.length && mapped[0] === arrays[0])
    ? baseIntersection(mapped, undefined, comparator)
    : []
}

duangduangduang,核心算法出爐。

// baseIntersection
function baseIntersection(arrays, iteratee, comparator) {
  // includes方法,判斷數(shù)組array中是否含有目標元素value
  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進行查詢的數(shù)組集合
  while (othIndex--) {
    // array為數(shù)組中的每個元素,即每個需要查詢的數(shù)組
    array = arrays[othIndex]
    if (othIndex && iteratee) {
      array = map(array, (value) => iteratee(value))
    }
    maxLength = Math.min(array.length, maxLength)
    // 設置緩存集合,緩存集合caches的每個元素標識與之相對應的數(shù)組元素是否需要緩存
    caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
      ? new SetCache(othIndex && array)
      : undefined
  }
  // 將array中的第一個元素設置為比較標準
  array = arrays[0]

  let index = -1
  const seen = caches[0]

  outer:
  while (++index < length && result.length < maxLength) {
    // 外層遍歷:遍歷array數(shù)組中的每個元素,賦值為value
    let value = array[index]
    const computed = iteratee ? iteratee(value) : value

    value = (comparator || value !== 0) ? value : 0
    // 判斷條件:若結(jié)果數(shù)組result中不包含當前元素value,繼續(xù)執(zhí)行算法。
    if (!(seen
          ? cacheHas(seen, computed)
          : includes(result, computed, comparator)
        )) {
      othIndex = othLength
      while (--othIndex) {
        const cache = caches[othIndex]
        // 內(nèi)層遍歷:遍歷arrays數(shù)組集合除了第一項的所有數(shù)組,如果該數(shù)組包含value元素,將元素push到result中
        if (!(cache
              ? cacheHas(cache, computed)
              : includes(arrays[othIndex], computed, comparator))
            ) {
          continue outer
        }
      }
      if (seen) {
        seen.push(computed)
      }
      result.push(value)
    }
  }
  return result
}
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容