_.intersectionWith([arrays], [comparator])
Arrays _. Comparator
2023-09-11 14:15:02 时间
23
_.intersectionWith([arrays], [comparator])
_.intersectionWith和_.intersection一样,取数组的交集,区别是传入自定义的比较器
参数
[arrays] (...Array): 需要取交集的数组组成的数组
[comparator] (Function): 比较器
返回值
(Array):返回交集元素组成的新数组
例子
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; _.intersectionWith(objects, others, _.isEqual); // => [{ 'x': 1, 'y': 2 }]
源代码:
import map from './map.js' import baseIntersection from './.internal/baseIntersection.js' import castArrayLikeObject from './.internal/castArrayLikeObject.js' import last from './last.js' /** * This method is like `intersection` except that it accepts `comparator` * which is invoked to compare elements of `arrays`. The order and references * of result values are determined by the first array. The comparator is * invoked with two arguments: (arrVal, othVal). * * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of intersecting values. * @example * * const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] * const others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }] * * intersectionWith(objects, others, isEqual) * // => [{ 'x': 1, 'y': 2 }] */ //和intersection一样,取数组的交集,区别是传入自定义的比较器 function intersectionWith(...arrays) { let comparator = last(arrays)//最后一个参数是比较器 const mapped = map(arrays, castArrayLikeObject)//循环参数数组,将不是array-like对象的参数都转变成空数组 comparator = typeof comparator == 'function' ? comparator : undefined//判断比较器不是函数的情况就赋值undefined if (comparator) {//如果传递了比较器参数,就去掉map后的参数数组的最后一个元素 mapped.pop() } return (mapped.length && mapped[0] === arrays[0]) ? baseIntersection(mapped, undefined, comparator) : [] //如果参数数组长度不为0,且第一个参数数组是array-like对象,就调用baseIntersection处理 //否则,返回空数组 } export default intersectionWith
下面是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
相关文章
- [Python] Boolean Or "Mask" Index Arrays filter with numpy
- [Typescript] Sorting arrays in TypeScript
- C++ code:char pointers and char arrays(字符指针与字符数组)
- [Ramda] Get a List of Unique Values From Nested Arrays with Ramda (flatMap --> Chain)
- [LeetCode] Intersection of Two Arrays
- Difference between ArrayList and Arrays.asList() in Java
- 成功解决TypeError: only size-1 arrays can be converted to Python scalars
- 【Java编程】之 List 与数组之间的相互转换&Arrays.asList 和 ArrayList 的 subList
- LeetCode Median of Two Sorted Arrays