lodash-8 pull,pullAll,pullAllBy,pullAllWith
前言
今天是 lodash
的第 8 天,今天带来的是 pull
,pullAll
,pullAllBy
,pullAllWith
已经坚持写了 8 篇了,加油!
Api
_.pull(array, [values])
Removes all given values from array
using SameValueZero
for equality comparisons.
Arguments
array
(Array) : The array to modify.[values]
(...)* : The values to remove.
Returns
(Array) : Returns array
.
Example
var array = ['a', 'b', 'c', 'a', 'b', 'c'];
_.pull(array, 'a', 'c');
console.log(array);
// => ['b', 'b']
删除数组中的给定的元素
source
简化版
function pull(array, ...values) {
return basePullAll(array, values);
}
使用 「剩余参数」 语法, 传入 a,c
到 values 会转化为 [a,c]
🔥🔥🔥 basePullAll 简化版
function basePullAll(array,values){
var index = -1,length = values.length;
while (++index < length) {
var fromIndex = 0,
value = values[index];
// 使用 indexOf 找到下标
while ((fromIndex = array.indexOf(value)) > -1) {
array.splice(fromIndex, 1);
}
}
}
遍历 values
,获取单个元素 value
使用 indexOf
找到在 array
中的value
下标
然后使用 splice
删除元素
pullAll(array, values)
var array = ['a', 'b', 'c', 'a', 'b', 'c'];
_.pullAll(array, ['a', 'c']);
console.log(array);
// => ['b', 'b']
和 pull
的区别是 pullAll
是接收的一个数组,
不使用剩余语法即可
function pull(array, values) {
return basePullAll(array, values);
}
pullAllBy(array, values, [iteratee=_.identity])
This method is like _.pullAll
except that it accepts iteratee
which is invoked for each element of array
and values
to generate the criterion by which they're compared. The iteratee is invoked with one argument: (value) .
Arguments
array
(Array) : The array to modify.values
(Array) : The values to remove.[iteratee=_.identity]
(Function) : The iteratee invoked per element.
Returns
(Array) : Returns array
.
Example
var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
_.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
console.log(array);
// => [{ 'x': 2 }]
与上面的相比,多了一个 参数 "x", 如果 "x" 对应的 value 值相同,则删除
对 pullAllBy
进行改造,传入一个 iteratee
function pullAllBy(array, values, iteratee){
return basePullAll(array, values, (object)=>object[iteratee])
}
在 上文中 iteratee
是 "x", 当后续调用 (object)=>object[iteratee])
会传递参数 object
,获取 x 对应的 value 值
那么 basePullAll
要加上一个 iteratee
参数
basePullAll
pullAllBy(
[{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }],
[{ 'x': 1 }, { 'x': 3 }],
'x'
)
function pullAllBy(array, values, iteratee){
return basePullAll(
[{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }],
[{ 'x': 1 }, { 'x': 3 }],
(object)=>object['x'])
}
以☝️上文的参数为例
// iteratee = (object)=>object[x]
function basePullAll(array,values,iteratee){
var index = -1,length = values.length,seen = array;
if(iteratee){
seen = array.map((item)=>{
return iteratee(item)
})
// 可以简写成下文 pointfree
// seen = array.map(iteratee)
}
// [1,2,3,1]
console.log( seen );
while (++index < length) {
var fromIndex = 0,
value = values[index],
// 也对数组中的每一项执行相同的操作
// computed = 1 , 3
computed = iteratee ? iteratee(value) : value;
while ((fromIndex = seen.indexOf(computed)) > -1) {
// 说明已经使用迭代器过滤过,因为上文中初始化是 seen = array
if(seen != array){
seen.splice(fromIndex, 1);
}
array.splice(fromIndex, 1);
}
}
return array
}
使用迭代器 iteratee
把 数组对象提取出对应的值,得到一个只有值的数组 seen
,然后通过判断格式化的元素(computed
) 在 seen
中的下标,然后使用 splice
删除
还是比较好理解的
_.pullAllWith(array, values, [comparator])
var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
_.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
console.log(array);
// => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
比较数组对象,如果数组对象中的相同对象,则删除
比较两个对象是否相等的方法 isEqual
简化版
isEqual
function isEqual(value1,value2){
let k1 = Object.keys(value1),k2 = Object.keys(value2);
// 首先比较两个对象的长度
if(k1.length != k2.length)return false;
// 比较对应的 k 的value 值
for(let k in value1){
if(!(k in value2) || value2[k] != value1[k]){
return false
}
}
return true
}
对 basePullAll
进行处理,传入自定义的比较方法
source
function pullAllWith(array, values, comparator){
return basePullAll(array, values,undefined, comparator)
}
只需要把 以前的 判断条件 indexOf
换成用户传递的即可🐼
basePullAll
function basePullAll(array,values,iteratee,comparator){
var index = -1,length = values.length,seen = array;
// 🚀🚀🚀 重新设计 比较方法
var indexOf = comparator ? baseIndexOfWith : baseIndexOf;
if(iteratee){
seen = array.map(iteratee)
}
while (++index < length) {
var fromIndex = 0,
value = values[index],
computed = iteratee ? iteratee(value) : value;
while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
if(seen != array){
seen.splice(fromIndex, 1);
}
array.splice(fromIndex, 1);
}
}
return array
}
baseIndexOfWith
使用自定义的比较器
function baseIndexOfWith(array, value, fromIndex, comparator) {
var index = fromIndex - 1,
length = array.length;
while (++index < length) {
if (comparator(array[index], value)) {
return index;
}
}
return -1;
}
baseIndexOf
indexOf
function baseIndexOf(array, value, fromIndex) {
var index = fromIndex - 1,
length = array.length;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
最后
慢慢的,当找到方法后, 看源码的速度越来越快, lodash
的很多衍生方法都是基于一个 base方法
,然后传入不同的参数, 今天的也不例外
不断的对函数式编程有更深刻的理解
目前,我对函数式编程的理解是告诉我要什么,而不是怎么做,类似于数学中的 f(x)
比如 Math.abs
,我不管内部是如何实现,但是给我一个准确的结果,函数式更多的关注是结果,而不是运算过程
转载自:https://juejin.cn/post/7249934982113869879