知识点
concat
方法可以接受数组作为参数,也可以接受非数组成员作为对象- 递归
reduce
方法- 判断数组类型
flat
方法
题目
编写一个JavaScript
函数,接受一个仅包含数字的多维数组,返回拍平以后的结果。例如传入:[1, [2, [3, [4], 5], 6], 7]
,返回[1, 2, 3, 4, 5,6,7]
。
实现1
明显要通过递归实现,可以使用reduce
方法,它可以保存当前只执行过的结果在total
中,如果当前项目current
仍然是数组,那么需要将递归执行的结果与total
拼接
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
方法,通过递归实现,构造一个闭包,通过闭包中的变量来传递结果
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
也可以不使用递归,直接使用循环实现
// ES6
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;
}
// ES5
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实现:
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()
方法会移除数组中的空项
function flatDeep5(arr) {
return arr.flat(Infinity);
}