_.intersectionBy([arrays], [iteratee=_.identity])
identity Arrays _.
2023-09-11 14:15:02 时间
22
_.intersectionBy([arrays], [iteratee=_.identity])
_.intersectionBy类似intersection方法,取数组的交集,区别是多传递一个迭代器函数
参数
[arrays] (...Array): 需要取交集的数组组成的数组
[iteratee=_.identity] (Function): 迭代器
返回值
(Array):返回交集元素组成的新数组
例子
_.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // => [2.1] // The `_.property` iteratee shorthand. _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); // => [{ 'x': 1 }]
源代码:
最终生成的代码里iteratee迭代器参数被_.iteratee处理以操作对象属性的情况,这里和differenceBy的源码同理,所以省略。
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 `iteratee` * which is invoked for each element of each `arrays` to generate the criterion * by which they're compared. The order and references of result values are * determined by the first array. The iteratee is invoked with one argument: * (value). * * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Function} iteratee The iteratee invoked per element. * @returns {Array} Returns the new array of intersecting values. * @example * * intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor) * // => [2.1] */ //类似intersection方法,取数组的交集,区别是多传递一个迭代器函数 function intersectionBy(...arrays) { let iteratee = last(arrays)//最后一个参数是迭代器 const mapped = map(arrays, castArrayLikeObject)//循环参数数组,将不是array-like对象的参数都转变成空数组 if (iteratee === last(mapped)) {//如果map处理后的最后一个元素和没处理的最后一个元素相等,说明没有传递iteratee,设置为undefined iteratee = undefined } else {//否则,去除map从处理后的最后一个元素 mapped.pop() } return (mapped.length && mapped[0] === arrays[0]) ? baseIntersection(mapped, iteratee) : [] //如果参数数组长度不为0,且第一个参数数组是array-like对象,就调用baseIntersection处理 //否则,返回空数组 } export default intersectionBy
下面是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
相关文章
- [Typescript] 134. Easy - Identity Helper
- ASP.NET Identity
- [Typescript] 134. Easy - Identity Helper
- MVC5 - ASP.NET Identity登录原理 - Claims-based认证和OWIN
- SAP云平台Application Identity Provider和Identity federation
- Trial accounts of SAP Cloud Platform do not provide an Identity Authentication tenant
- Sherman–Morrison formula和Woodbury matrix identity
- No matching code signing identity found
- Identity and Access Management (IAM)
- 【Git技巧】第四篇 解决 “ Author identity unknown ”问题
- 【机器学习】前置知识:矩阵的表示与定义 | Identity 身份矩阵 | 逆矩阵和转置 | 标量乘法