本篇分析下intersection
家族的方法,包括intersection
、intersectionBy
、intersectionWith
以及核心方法baseIntersection
。最后给出intersection
方法的原生实现。
核心方法 baseIntersection
三个flatten
方法全都是封装的baseIntersection
方法,这个方法有三个参数:
arrays
是需要求交集的数组(array
)组成的数组(arrays
)。
iteratee
是array
中每个元素都要执行的迭代函数,执行完再进行求交集,主要服务给intersectionBy
用。
comparator
是array
中每个元素都要执行的比较器函数,用于设定如何比较的规则,主要服务给intersectionWith
用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| import SetCache from './SetCache.js'; import arrayIncludes from './arrayIncludes.js'; import arrayIncludesWith from './arrayIncludesWith.js'; import map from '../map.js'; import cacheHas from './cacheHas.js';
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;
while (othIndex--) { array = arrays[othIndex]; if (othIndex && iteratee) { array = map(array, (value) => iteratee(value)); } maxLength = Math.min(array.length, maxLength); caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) ? new SetCache(othIndex && array) : 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; if ( !(seen ? cacheHas(seen, computed) : includes(result, computed, comparator)) ) { othIndex = othLength; while (--othIndex) { const cache = caches[othIndex]; if ( !(cache ? cacheHas(cache, computed) : includes(arrays[othIndex], computed, comparator)) ) { continue outer; } } if (seen) { seen.push(computed); } result.push(value); } } return result; }
export default baseIntersection;
|
intersection 家族
intersection
intersection
方法是普通的求交集方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import map from './map.js'; import baseIntersection from './.internal/baseIntersection.js'; import castArrayLikeObject from './.internal/castArrayLikeObject.js';
function intersection(...arrays) { const mapped = map(arrays, castArrayLikeObject); return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : []; }
export default intersection;
|
intersectionBy
intersectionBy
方法是求交集前先将每个元素处理一遍。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import map from './map.js'; import baseIntersection from './.internal/baseIntersection.js'; import castArrayLikeObject from './.internal/castArrayLikeObject.js'; import last from './last.js';
function intersectionBy(...arrays) { let iteratee = last(arrays); const mapped = map(arrays, castArrayLikeObject);
if (iteratee === last(mapped)) { iteratee = undefined; } else { mapped.pop(); } return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, iteratee) : []; }
export default intersectionBy;
|
intersectionWith
intersectionWith
方法是求交集时选用不同的规则比较。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import map from './map.js'; import baseIntersection from './.internal/baseIntersection.js'; import castArrayLikeObject from './.internal/castArrayLikeObject.js'; import last from './last.js';
function intersectionWith(...arrays) { let comparator = last(arrays); const mapped = map(arrays, castArrayLikeObject);
comparator = typeof comparator === 'function' ? comparator : undefined; if (comparator) { mapped.pop(); }
return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined, comparator) : []; }
export default intersectionWith;
|
原生写法
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
1 2 3 4 5 6 7 8 9 10 11 12
| let arrays = [ [1, 2, 3], [101, 2, 1, 10], [2, 1], ];
console.log( arrays.reduce((accumulator, currentValue) => accumulator.filter((item) => currentValue.includes(item)) ) );
|