V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
supermao
V2EX  ›  程序员

JavaScript30 秒, 从入门到放弃之 Array(三)

  •  
  •   supermao ·
    hongmaoxiao · 2017-12-31 00:35:25 +08:00 · 2128 次点击
    这是一个创建于 2301 天前的主题,其中的信息可能已经有所发展或是发生改变。

    flattenDepth

    Flattens an array up to the specified depth.

    Use recursion, decrementing depth by 1 for each level of depth. Use Array.reduce() and Array.concat() to merge elements or arrays. Base case, for depth equal to 1 stops recursion. Omit the second element, depth to flatten only to a depth of 1 (single flatten).

    const flattenDepth = (arr, depth = 1) =>
      depth != 1
        ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
        : arr.reduce((a, v) => a.concat(v), []);
    

    把一个数组按指定深度进行摊平。

    使用递归方法,对于任意级别的深度depth,每次递归depth1。使用Array.reduce()Array.concat()来合并元素们或者数组们。直到depth递减到1时停止递归。省略第二个参数depth时,按深度depth1计(即单层摊平)。

    ➜  code cat flattenDepth.js
    const flattenDepth = (arr, depth = 1) =>
        depth != 1 ?
        arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), []) :
        arr.reduce((a, v) => a.concat(v), []);
    
    console.log(flattenDepth([1, [2], 3, 4]));
    console.log(flattenDepth([1, [2, [5]], 3, 4]));
    ➜  code node flattenDepth.js
    [ 1, 2, 3, 4 ]
    [ 1, 2, [ 5 ], 3, 4 ]
    

    根据depth来决定处理流程,depth存在且不等于1则进行递归:

    arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
    

    用了reduce()去处理循环时的每一个值,同时用concat把所有递归结果拼接成新数组返回。循环过程中,对值进行数组判断Array.isArray(v),是数组,flattenDepth(v, depth - 1)深度减1继续递归直到depth1为止;不是数组,直接返回该值v,供concat拼接。

    否则,直接循环去拼接该值返回:

    arr.reduce((a, v) => a.concat(v), []);
    

    groupBy

    Groups the elements of an array based on the given function.

    Use Array.map() to map the values of an array to a function or property name. Use Array.reduce() to create an object, where the keys are produced from the mapped results.

    const groupBy = (arr, func) =>
     arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
       acc[val] = (acc[val] || []).concat(arr[i]);
       return acc;
     }, {});
    

    按照指定的方法对数组元素进行分组归类。

    使用Array.map()对所有数组元素调用指定方法或者调用返回该元素的属性值的方法。使用Array.reduce()创建一个对象,对象的键是map生成的结果,值是符合该键的所有数组元素组成的数组。

    ➜  code cat groupBy.js
    const groupBy = (arr, func) =>
        arr.map(typeof func === 'function' ? func : val => val[func]).
    reduce((acc, val, i) => {
        acc[val] = (acc[val] || []).concat(arr[i]);
        return acc;
    }, {});
    
    console.log(groupBy([6.1, 4.2, 6.3], Math.floor));
    console.log(groupBy(['one', 'two', 'three'], 'length'));
    ➜  code node groupBy.js
    { '4': [ 4.2 ], '6': [ 6.1, 6.3 ] }
    { '3': [ 'one', 'two' ], '5': [ 'three' ] }
    

    代码拆分:

    1. map
    arr.map(typeof func === 'function' ? func : val => val[func])
    

    对第二个参数func的类型进行判断,若是function,则对数组arr所有元素调用该方法,返回一个新的数组。如:

    const arr = [1, 2, 3, 4];
    arr.map(x => x * x); // [1, 4, 9, 16]
    

    否则,调用返回该元素对应func属性值方法:

    const arr = ['one', 'two', 'three'];
    const func = 'length';
    arr.map(val => val[func]); // [3, 3, 5]
    
    1. reduce
    reduce((acc, val, i) => {
      acc[val] = (acc[val] || []).concat(arr[i]);
      return acc;
    }, {})
    

    accreduce过程中累积的结果,valreduce的主体(即前边map的结果数组)每次循环时数组元素的值,i则是主体数组循环时对应的索引。

    第一个循环时acc的初始值是一个空对象{},循环过程中先判断是否已经有以val为键的值,如果还没有,创建一个空数组把此时对应索引i的数组值arr[i]拼接,作为以val为键的值;否则,直接拼接arr[i]。即是acc[val] = (acc[val] || []).concat(arr[i])做的事。每次循环都返回acc对象,直到循环结束,生成分类结果。

    连起来就是说先对数组arr元素进行mapmap结果作为键,所有map结果相同的数组元素arr[i]归到一个数组中作为该键的值。最终返回一个分好类的对象。

    head

    Returns the head of a list.

    Use arr[0] to return the first element of the passed array.

    const head = arr => arr[0];
    

    返回数组第一个元素。

    使用arr[0]返回指定数组arr的第一个元素。

    ➜  code cat head.js
    const head = arr => arr[0];
    
    console.log(head([1, 2, 3]));
    ➜  code node head.js
    1
    

    initial

    Returns all the elements of an array except the last one.

    Use arr.slice(0,-1) to return all but the last element of the array.

    const initial = arr => arr.slice(0, -1);
    

    返回除数组最后一个元素外的所有元素组成的新数组。

    使用arr.slice(0, -1)返回数组除最后一个元素外的所有元素。

    ➜  code cat initial.js
    const initial = arr => arr.slice(0, -1);
    
    console.log(initial([1, 2, 3]));
    ➜  code node initial.js
    [ 1, 2 ]
    

    arr.slice(0, -1)立竿见影,实在没啥可说。

    initialize2DArray

    Initializes a 2D array of given width and height and value.

    Use Array.map() to generate h rows where each is a new array of size w initialize with value. If the value is not provided, default to null.

    const initialize2DArray = (w, h, val = null) =>
     Array(h)
       .fill()
       .map(() => Array(w).fill(val));
    

    初始化一个给定宽(列)、高(行)和值的二维数组。

    使用Array.map()来生成一个h行的数组。每一行含有w个值为指定值的元素。如果未指定任何值,数组的默认值是null

    ➜  code cat initialize2DArray.js
    const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val));
    
    console.log(initialize2DArray(2, 2, 0));
    ➜  code node initialize2DArray.js
    [ [ 0, 0 ], [ 0, 0 ] ]
    

    Array(h).fill()先创建一个含有h个元素的数组并将它们全部默认填充为undefined。然后在生成的数组基础上,每个数组元素调用一个生成w个元素的数组且每个位置的值都填充为val方法。这样就生成了hw列的二维数组。

    完整版在这:JavaScript30 秒, 从入门到放弃之 Array (三)

    另外,打一波广告:一个时间处理库:now.js,觉得还行的话,点个赞再走呗。。。

    微信公众号:JavaScript30 秒, 从入门到放弃之 Array (三)

    2 条回复    2018-01-01 06:33:21 +08:00
    mingyun
        1
    mingyun  
       2018-01-01 00:22:17 +08:00
    新年好啊,star 了
    supermao
        2
    supermao  
    OP
       2018-01-01 06:33:21 +08:00 via iPhone
    @mingyun 新年快乐🎉🎉🎉,谢谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5326 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 07:51 · PVG 15:51 · LAX 00:51 · JFK 03:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.