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