likes
comments
collection
share

lodash-11 zip,unzip,zipObject, zipWith

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

前言

今天是 lodash 的系列,今天带来 zipunzip

Api

zip

Creates an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on.

Arguments

  1. [arrays]  (...Array) : The arrays to process.

Returns

(Array) : Returns the new array of grouped elements.

Example

_.zip(['a''b'], [12], [truefalse]);
// => [['a', 1, true], ['b', 2, false]]

可以看到 zip 把参数做了一个整合

source

var baseRest = require('./_baseRest'),
    unzip = require('./unzip');
var zip = baseRest(unzip);

可以简化成

function unzip(array){
 // xxxx
}

主要逻辑在 unzip

先看 unzip 源码

// array = [['a', 'b'], [1, 2], [true, false]]
function unzip(array) {
  if (!(array && array.length)) {
    return [];
  }
  var length = 0;
  array = arrayFilter(array, function(group) {
    if (isArrayLikeObject(group)) {
      length = Math.max(group.length, length);
      return true;
    }
  });
  
  return baseTimes(length, function(index) {
    return arrayMap(array,  baseProperty(index));
  }); 
}

先从函数名中我们就可以看出大概思路

  1. 使用 arrayFilter 过滤掉非 isArrayLikeObject 的元素,同时使用 nativeMax 获取元素中的最大长度 length
  2. baseTimes 的作用是执行 length 次的 function
  3. arrayMap 的作用是对数组执行相同的迭代操作,并返回迭代后结果为 true 的元素组成的一个数组
  4. baseProperty 返回一个函数

组合起来,说白了就是两层嵌套循环

外层循环元素的最大的元素长度 比如 ['a', 'b'], [1, 2], [true, false] 的最大长度是 2

内层循环遍历单个元素返回 元素[index] 组成的数组

arrayMap(array,  baseProperty(index))
可以写成这样
array.map(item=>item[index])

其实就是,也就是对内层元素取 index对应的 value
比如 index = 0,那么 array.map(item=>item[0])
item 就是 [a,b] / [1,2] / [true,false] 

所以我们可以写成这样

function zip2 (...values){
 // 求出元素中的最大长度
  let length = values.reduce((prev,cur)=>{
    return Math.max(prev,cur.length)
  },0);
  
  let array = values;
  let result = [];

  for(let i = 0;i < length;i++){
    result[i] = array.map((item)=>{
      return item[i]
    })
  }
  return result
  // return baseTimes(length, function(index) {
  //   return arrayMap(array,  baseProperty(index));
  // });
}
zip2(['a', 'b'], [1, 2], [true, false])
// [ [ 'a', 1, true ], [ 'b', 2, false ]]

如果有兴趣,可以查看每一个函数的代码

arrayFilter

function arrayFilter(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length,
      resIndex = 0,
      result = [];

  while (++index < length) {
    var value = array[index];
    if (predicate(value, index, array)) {
      result[resIndex++] = value;
    }
  }
  return result;
}

baseTimes

function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

arrayMaps

function arrayMap(array, iteratee) {
  var index = -1,
      length = array == null ? 0 : array.length,
      result = Array(length);

  while (++index < length) {
    result[index] = iteratee(array[index], index, array);
  }
  return result;
}

baseProperty

function baseProperty(key){
    return (object)=>{
        return object[key]
    }
}

_.zipObject([props=[]], [values=[]])

This method is like _.fromPairs except that it accepts two arrays, one of property identifiers and one of corresponding values.

Arguments

  1. [props=[]]  (Array) : The property identifiers.
  2. [values=[]]  (Array) : The property values.

Returns

(Object) : Returns the new object.

Example

_.zipObject(['a''b'], [12]);
// => { 'a': 1, 'b': 2 }

这个方法比较简单,就是前面的元素作为key,后面的作为 value 值

function baseZipObject(props, values) {
  var index = -1,
      length = props.length,
      valsLength = values.length,
      result = {};
// 保证有key 值
  while (++index < length) {
  // value 可以是 undefined
    var value = index < valsLength ? values[index] : undefined;
    result[props[index]] = value
  }
  return result;
}

_.zipWith([arrays], [iteratee=_.identity])

This method is like _.zip except that it accepts iteratee to specify how grouped values should be combined. The iteratee is invoked with the elements of each group:  (...group) .

Arguments

  1. [arrays]  (...Array) : The arrays to process.
  2. [iteratee=_.identity]  (Function) : The function to combine grouped values.

Returns

(Array) : Returns the new array of grouped elements.

Example

_.zipWith([12], [1020], [100200], function(a, b, c) {
  return a + b + c;
});
// => [111, 222]

source

 // [ [ 1, 10, 100 ], [ 2, 20, 200 ] ]

function unzipWith(array, iteratee) {
  if (!(array && array.length)) {
    return [];
  }
  // [ [ 1, 10, 100 ], [ 2, 20, 200 ] ]
  var result = unzip(array);
 
  if (iteratee == null) {
    return result;
  }

// 可以替换成
// return result.map(group=>{
//   return iteratee.apply(undefined, group)
// })
 return arrayMap(result, function(group) {
    return apply(iteratee, undefined, group);
  });
}

首先第一步,使用unzip 格式化,然后使用 arrayMap 对每一个元素执行 iteratee

结尾

今天是第 11 天,感觉 lodash 不是很难了,不调试也能比较理解其中代码的含义了,一方面是因为我熟悉了 lodash 的结构,另一方面也是因为 lodash 的函数语义化足够清晰