likes
comments
collection
share

源码学习——lodash(七)

作者站长头像
站长
· 阅读数 43

前言

开发过程中我们想要获取几个数组的交集可以使用lodash中intersection方法,本节就来学习一下该系列的用法及源码。

intersection

intersection返回多个数组相同元素的数组,其中判断相同的标准是SameValueZero。

_.intersection([arrays])
_.intersection([1,2],[2,3])//[2]

该方法的效果很简单,我们可以把它当成一个算法题,思考一下如何高效正确的实现出来。

源码学习——lodash(七) 我的方法简单粗暴,核心思路就是将统计数组集合中元素出现的个数,出现个数等于arrays长度的就是我们想要的结果。

  • 首先非空判断,然后用for of循环数组集合,通过new Set()进行去重,避免原数组重复的元素影响结果。
  • 声明一个new Map(),用for of循环子数组,将元素当作key,出现个数为value添加到map中。
  • 再次利用for of循环map,将value等于数组长度的元素添加到result,最后返回result。 三次利用for of循环,下面我们就来看下lodash的实现:
function intersection(...arrays) {
const mapped = map(arrays, castArrayLikeObject);
return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
}
  1. 用map处理传递的参数,map函数类似于数组方法中的map,会循环数组元素,并返回执行函数后的结果。这里第二个参数是castArrayLikeObject,用来判断是否为对象或者数组。mapped就是过滤之后的结果,如果元素不为数组就是空数组。
function castArrayLikeObject(value) {
  return isArrayLikeObject(value) ? value : []
}
  1. 利用三目运算,符合条件就执行baseIntersection方法。 这里用map进行非空判断比自己写的简便多了,baseIntersection方法我们后面再统一讲解。

intersectionBy与intersectionWith

intersectionBy在上面方法基础上多了一个iteratee迭代器参数,它会先处理每个元素然后再进行比较。注意,返回的结果依旧是原数组的元素,并且从第一个数组获取。

_.intersectionBy([arrays],iteratee)
_.intersectionBy([1.1,2.1],[2.2,3.2],Math.floor)//[2.1]

源码学习——lodash(七) 对比intersection多了一步处理,利用last获取迭代函数,然后将其当做参数传递给base方法。last上节我们刚好讲解过,用来获取数组最后一个元素。 intersectionWith多了一个comparato比较器参数,返回满足比较器的原数组元素,结果依旧是从第一个数组获取。

_.intersectionWith([arrays], comparator)

源码学习——lodash(七) 基本跟intersectionBy一样,就是将comparato进行了类型判断,确保为函数,然后当作第三个传递给了对应的base方法。到此我们能够知道baseIntersection至少有三个参数,下面我们来解析其源码,源码内容过多,我们分两部分解析:

源码学习——lodash(七)

  1. 首先利用三目运算判断comparato获取includes函数,用来判断数组是否有某个值,有两种方法arrayIncludesWith、arrayIncludes。很明显comparator就是with方法所用。接着就是length及空数组的声明,length为第一个元素数组的长度,othLength为整个数组的长度,我们要区分开。
  2. 接着用while循环处理整个数组,判断iteratee参数,如果存在通过map得到处理过后的元素数组。接着就是三目运算,满足条件就会使用new SetCache将数据进行缓存,SetCache是一个类,里面有add和has方法,add添加元value,has获取value。 经过以上操作我们就可以得到处理过后的数组caches,接着我们看下剩余代码: 源码学习——lodash(七) 这部分就是核心源码,看起来很复杂,直接说下核心思路:循环第一组的元素,将其与其他元素数组进行对比,如果其他元素数组都存在此元素就添加到result里面,这也就解释了By与with为什么返回的是第一个数组的元素。
  • 第一个while循环第一组元素数组array,获取对比值computed。
  • 第二个while循环其他元素数组,将里面的元素与computed做对比,有一组不相等就继续循环array的下一个,也就是continue outer。这里对比有两者一个是cacheHas用于对象元素判断,一个是includes用于数组元素判断。 很明显lodash的方法更加全面,而且都是用while循环数组获取结果,没有依赖于es6语法。

总结

以上就是intersection系列方法,其中的核心方法baseIntersection比较复杂,需要我们去梳理思考一下。

转载自:https://juejin.cn/post/7352387578908934196
评论
请登录