likes
comments
collection
share

lodash-8 pull,pullAll,pullAllBy,pullAllWith

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

前言

今天是 lodash 的第 8 天,今天带来的是 pull,pullAll,pullAllBy,pullAllWith

已经坚持写了 8 篇了,加油!

Api

_.pull(array, [values])

Removes all given values from array using SameValueZero for equality comparisons.

Arguments

  1. array  (Array) : The array to modify.
  2. [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

  1. array  (Array) : The array to modify.
  2. values  (Array) : The values to remove.
  3. [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
评论
请登录