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

2017-12-31 00:35:25 +08:00
 supermao

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 (三)

2130 次点击
所在节点    程序员
2 条回复
mingyun
2018-01-01 00:22:17 +08:00
新年好啊,star 了
supermao
2018-01-01 06:33:21 +08:00
@mingyun 新年快乐🎉🎉🎉,谢谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/418952

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX