lodash系列-3 drop, dropRight,dropRightWhile,dropWhile

前言

今天看看 drop, dropRight,dropRightWhile,dropWhile,方法相似,又是经典的一个底层方法根据传入不同参数的例子

Api

_.drop(array, [n=1])

Creates a slice of array with n elements dropped from the beginning.

Arguments

  1. array  (Array) : The array to query.
  2. [n=1]  (number) : The number of elements to drop.

Returns

(Array) : Returns the slice of array.

Example

_.drop([1, 2, 3]);
// => [2, 3]
 

_.drop([1, 2, 3], 2);
// => [3]
 


_.drop([1, 2, 3], 5);
// => []
 


_.drop([1, 2, 3], 0);
// => [1, 2, 3]

也就是从左边删除 n 个元素

source

function drop(array, n, guard) {
  var length = array == null ? 0 : array.length;
  if (!length) {
    return [];
  }

  n = (guard || n === undefined) ? 1 : toInteger(n);
  return baseSlice(array, n < 0 ? 0 : n, length);
}

可以简化为

function drop(array, n) {
  n = (n === undefined) ? 1 : Math.floor(n);
  return baseSlice(array, n, array.length);
}

来看看 baseSlice 方法

baseSlice

function baseSlice(array, start, end) {
    var index = -1,
      length = array.length;




  // 可以传入 负数,说明是从后往前计算,所以是 start +  length 
  if (start < 0) {
    start = -start > length ? 0 : (length + start);
  }
  
  // 取 end 与 length 的最小值,保证不会越界
  // Math.min(undefined,0) 是NaN,所以使用判断
  end = end > length ? length : end;


// 判断 start 与 end 的关系
// 如果 start 比 end 大,说明不合法, 0
  length = start > end ? 0 : end - start;


  // 取 start 与 end 之间的值
  var result = Array(length);
  
  while (++index < length) {
    result[index] = array[index + start];
  }
  return result;
}

baseSlice 接受三个参数,分别是 原数组,切割的开始索引,结束索引
最后只需要 result[index] = array[index + start],也就是 result 是从 array 的 start下标 开始获取元素

baseSlice 返回一个从 start 到 end 之间的数组!

baseSlice 返回一个从 start 到 end 之间的数组!

baseSlice 返回一个从 start 到 end 之间的数组!

后面的 drop 衍生方法都是基于 baseSlice 方法!

当 调用drop([1, 2, 3])的时候,因为第二个参数即 baseSlicestart 值,默认是 1,所以 result[index] = array[index + 1],从下标为 1 开始赋值

所以当你看到 drop([1, 2, 3], 2) 或者 drop([1, 2, 3], 5) 的时候,就知道 start 是从 2或者从 5 开始,end 值是 array.length

当明白了这个道理,那 dropRight 也是一样的

dropRight(array, [n=1])

Creates a slice of array with n elements dropped from the end.

Arguments

  1. array  (Array) : The array to query.
  2. [n=1]  (number) : The number of elements to drop.

Returns

(Array) : Returns the slice of array.

Example

_.dropRight([1, 2, 3]);
// => [1, 2]
 

_.dropRight([1, 2, 3], 2);
// => [1]
 


_.dropRight([1, 2, 3], 5);
// => []
 


_.dropRight([1, 2, 3], 0);
// => [1, 2, 3]

从右边删除 n 个元素

function dropRight(array, n) {



  var length = array == null ? 0 : array.length;


  n = (n === undefined) ? 1 : Math.floor(n);



  n = length - n;

  return baseSlice(array, 0,  Math.max(0,n));
}

dropRight 是从 0 开始,截取到 length - n,n 默认是 1

所以当调用 dropRight([[1, 2, 3]) 的时候,start 是 0, end 是 length - n2 ,
当调用 dropRight([1, 2, 3], 2) 的时候, start 是 0, end 是 length - n1

由于 baseSlice 是获取 start-end 之间的元素,dropRight 是 [0 – length-n] 所以相当于 删除了后几位

dropWhile

Creates a slice of array excluding elements dropped from the beginning. Elements are dropped until predicate returns falsey. The predicate is invoked with three arguments:  (value, index, array) .

Arguments

  1. array  (Array) : The array to query.
  2. [predicate=_.identity]  (Function) : The function invoked per iteration.

Returns

(Array) : Returns the slice of array.

Example

var users = [
  { 'user': 'barney',  'active': false },
  { 'user': 'fred',    'active': false },
  { 'user': 'pebbles', 'active': true }
];
 


_.dropWhile(users, function(o) { return !o.active; });
// => objects for ['pebbles']
 


// The `_.matches` iteratee shorthand.
_.dropWhile(users, { 'user': 'barney', 'active': false });
// => objects for ['fred', 'pebbles']
 
// The `_.matchesProperty` iteratee shorthand.
_.dropWhile(users, ['active', false]);
// => objects for ['pebbles']
 
// The `_.property` iteratee shorthand.
_.dropWhile(users, 'active');
// => objects for ['barney', 'fred', 'pebbles']

dropWhile 返回不满足后面条件的元素

可以看到 这个 dropWhile 可以接受多种类型的条件

  1. 函数 function(o) { return !o.active; }
  2. 对象 { 'user': 'barney', 'active': false }
  3. 数组  ['active', false]
  4. 字符串 active

source

function dropWhile(array, predicate) {
  return (array && array.length)

    ? baseWhile(array, baseIteratee(predicate), true)
    : [];

}

baseWhile


function baseWhile(array, predicate, isDrop, fromRight) {
  var length = array.length,
      index = fromRight ? length : -1;


    // 对每一项执行  predicate 操作,如果 predicate 为 true 就一直执行,不断地改变 index
    // 直到 执行结果 false
    
    // 这一步是为了 锁定位置
    // 如果是正常的从左到右,index 则是 起始位置
    // 如果是 从 右到左,index 是结束位置
  while ((fromRight ? index-- : ++index < length) &&
    predicate(array[index], index, array)) {}





    // 如果是移除元素
     // fromRight 是 true
        // baseSlice(array,0,index+1)
      // 如果 是false 
        // baseSlice(array,index,length)
    
      // 如果不是
        // fromRight 是 true
        // baseSlice(array,index + 1,length)
      // 如果 是false 
        // baseSlice(array,0,index)
  return isDrop
    ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
    : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
}

可以看出 dropWhile 中支持多种条件,那么我们必须要格式化条件,转化为统一格式

baseIteratee 简化版

var baseIteratee = value => {
// 函数类型
  if (typeof value == "function") {
    return value;
  }




  // 对象 包含 数组 / 对象
  if (typeof value == "object") {
  // 如果是数组 ['active', false],
  // 那么 value[0] 是 active,value[1] 是 false
    return isArray(value)
      ? (object)=> {
          if(object == null) return false;
          return object[value[0]] == value[1] 
      }
      // 对象类型
      // { 'user': 'pebbles', 'active': false }
      : baseMatches(value);
  }

  
  // 字符串类型
  return ( key ) => function (object) {
    return object == null ? undefined : object[key];
  };
};

{ 'user': 'barney', 'active': false } 为例,

baseMatches
function baseMatches(source) {



    // source 是 用户传递进来的查询条件 { 'user': 'barney', 'active': false }
     var matchData = Object.entries(source); // [[user, barney],[active,false]]
     
     return function (object){
     
         // 如果是同一个引用就不用判断了
         return object === source || baseIsMatch(object, matchData)
     }
}

拿着用户传递进来的查询条件逐条与 source 数组的每一项进行比对

baseIsMatch
function baseIsMatch(object, matchData) {



// matchData ->  [[user, barney],[active,false]]
// object -> source 数组 的每一项
// source 是用户传递的判断对象条件



var index = -1,
  length = matchData.length;
  
  while (++index < length){
    data = matchData[index];
    var key = data[0], // key =  user 
      objValue = object[key], // user -> barney
      srcValue = data[1]; // barney


      if(srcValue !== objValue){
        return false
      }
  }

  return true
}

如果发现 用户传递的 source 与 原数组的中的一条 objValue不相同,直接 retrurn false,那么 baseMatches 函数就会退出,然后返回一个 false,当 baseMatches 一旦退出,baseIteratee 也要退出执行,baseWhile 中的 predicate 也要退出执行

Untitled-2023-03-25-1222.png

dropRightWhile

和 dropWhile 一样,只是多加一个参数

function dropRightWhile(array, predicate) {
  return (array && array.length)

    ? baseWhile(array, baseIteratee(predicate), true, true)
    : [];

}

传入第四个参数 true,这时 baseSlicestartend 就会改变切割位置

结尾

lodash 大都采用的都是函数式编程,这样的好处非常明显,大大的增加了复用性,因为没有相互引用,所以非常容易测试,可以通过不同的参数改变状态,也增加了灵活性

2023/6/24

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYCgqPHJ' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片