展平数组的几种方法。
知识点
concat
方法可以接受数组作为参数,也可以接受非数组成员作为对象
- 递归
reduce
方法
- 判断数组类型
flat
方法
题目
编写一个JavaScript
函数,接受一个仅包含数字的多维数组,返回拍平以后的结果。例如传入:[1, [2, [3, [4], 5], 6], 7]
,返回[1, 2, 3, 4, 5,6,7]
。
实现1
明显要通过递归实现,可以使用reduce
方法,它可以保存当前只执行过的结果在total
中,如果当前项目current
仍然是数组,那么需要将递归执行的结果与total
拼接
1 2 3 4 5 6
| const flatDeep = (arr) => { if (!Array.isArray(arr) || arr.length === 0) { return []; } return arr.reduce((total, current) => total.concat(Array.isArray(current) ? flatDeep(current) : current), []) };
|
实现2
可以不使用reduce
方法,通过递归实现,构造一个闭包,通过闭包中的变量来传递结果
1 2 3 4 5 6 7 8 9 10 11 12 13
| function flatDeep2(arr) { const result = []; (function _flat(array) { array.forEach(v => { if (Array.isArray(v)) { _flat(v) } else { result.push(v); } }) })(arr); return result; }
|
实现3
也可以不使用递归,直接使用循环实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| function flatDeep3_1(arr) { const stack = [...arr]; const result = []; while (stack.length > 0) { const target = stack.pop(); if (Array.isArray(target)) { stack.push(...target); } else { result.unshift(target); } } return result; }
function flatDeep3_2(arr) { const stack = [].concat(arr); const result = []; while (stack.length > 0) { const target = stack.pop(); if (Object.prototype.toString.call(target) === '[object Array]') { [].push.apply(stack, target); } else { result.unshift(target); } } return result; }
|
实现4
还可以利用Generator实现:
1 2 3 4 5 6 7 8 9 10 11 12
| function flatDeep4(arr) { function* _flatDeep(array) { for (const current of array) { if (Array.isArray(current)) { yield* _flatDeep(current); } else { yield current } } } return [..._flatDeep(arr)]; }
|
实现5
不考虑兼容性,还可以直接使用Array.prototype.flat(depth)
方法,其中depth
是要展开的深度,默认是1
,传入Infinity
作为深度,可以展开任意深度的嵌套数组。
要注意的是,flat()
方法会移除数组中的空项
1 2 3
| function flatDeep5(arr) { return arr.flat(Infinity); }
|
参考