源码学习——lodash(十二)

571 阅读3分钟

前言

本节我们继续学习lodash源码,在lodash中有union系列方法用于合并排序,uniq系列方法用于去重,下面我们就来学习一下这两个系列方法。

union系列

union系统有三种方法,首先就是union,它可以创建一个按照顺序排序的数组,并且数组里的元素都是唯一:

_.union([arrays])
// arrays 数据集合
_.union([3,2],[2,1]) //[3,2,1]

该效果实现起来可以分成三步:合并数组;排序;去重,每步都不难实现,下面我们来看下lodash源码处理:

QQ图片20240813215908.png
源码非常简单就是通过baseUniq方法进行处理,合并则是利用baseFlatten,该方法前面讲解过。
剩下两种方法unionBy与unionWith跟前面系列含义一样: unionBy接受iteratee进行迭代,unionWith接受一个comparator进行比较。

_.unionBy([arrays], [iteratee])
_.unionBy([1.2], [1.5, 2.5], Math.floor) //[1.2, 2.5]

_.unionWith([arrays], [comparator])
_.unionWith([1,2,3], [2,3], _.isEqual);//[2,3]

QQ图片20240813221431.png

QQ图片20240813221509.png
核心方法都是baseUniq,只是传递参数不同,并且都用了last获取最后一个参数,也就是iteratee与comparator,并对这两个参数进行了判断。union核心方法都是baseUniq,而baseUniq很明显跟uniq脱不了干系,下面我们来看下uniq系列的用法。

uniq系列

uniq返回一个去重后的数组,lodash的去重都是只保留第一次出现的元素,NaN这种不等于本身的也会被去重。

_.uniq(array)
_.uniq([1,NaN,NaN]) //[1,NaN]

该方法源码也很简单:

function uniq(array) {
return array != null && array.length ? baseUniq(array) : [];
}

uniqBy增加迭代参数,uniqWith增加比较函数:

_.uniqBy(array,iteratee)
_.uniqBy([2.1,2.2],Math.floor) //[2.1]

_.uniqWith(array,comparator)
_.uniqBy([2,2],_.isEqual) //[2]
function uniqBy(array, iteratee) {
return array != null && array.length ? baseUniq(array, iteratee) : [];
}
function uniqWith(array, comparator) {
comparator = typeof comparator === 'function' ? comparator : undefined;
return array != null && array.length ? baseUniq(array, undefined, comparator) : [];
}

这两个系列都用到了baseUniq,最后我们来分析下对应的源码,首先解析一下前半部分代码:

QQ图片20240814195513.png

  • 三个参数无需多讲,然后就是定义变量,index——下标;includes——检查数组是否包含某个元素,默认为arrayIncludesWith;isCommon区分方法。
  • 然后进行判断赋值,存在comparator将isCommon变为false;如果超出最大长度,不存在迭代函数就用createSet创建新的数组,并将上面变量进行对应的赋值;
  • 经过上面步骤,所需变量就会被赋值对应的值,重点是seen赋值逻辑。

QQ图片20240814203311.png

  • while循环数组,index与length作为判定条件,定义value与computed,一个是原值,一个是迭代后的值。
  • 接着进行if判断,isCommon为true表示数组长度符合且不是With方法;computed===computed是为了判断NaN这种特殊类型。
  • 满足上一步条件就循环seen数组跟computed做对比,如果存在相同的元素就跳出当前循环,否则就添加到result中达到去重目的。
  • 不满足就是NaN特殊类型先通过includes判断,seen是否包含computed,不包含就添加到result,包含则不添加。 去重的核心思路就是通过===与includes方法判断是否包含当前值,为了兼容其它方法,这里判断都是用包含处理值的数组seen与处理后的值computed进行判断,然后将原数组的值添加到result中。

总结

以上就是union与unip两个系列源码的解析,这个去重思路还是值得学习的。