方法一 循环 + concat + push
思路
- 循环判断数组的每一项是否是数组:
Array.isArray(arr[i])
- 是数组就递归调用上面的扁平化一层的代码
result = result.concat(flatten(arr[i]));
- 不是数组,直接通过push添加到返回值数组
function flatten(arr) {
let result = [];
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
result = result.concat(flatten(arr[i]));
} else {
result.push(arr[i])
}
}
return result
}
console.log(flatten(arr));
// forEach版
// 递归版本的反嵌套
function flatten(array) {
var flattend = [];
(function flat(array) {
array.forEach(function(el) {
if (Array.isArray(el)) flat(el);
else flattend.push(el);
});
})(array);
return flattend;
}
// 控制嵌套层数
// forEach 遍历数组会自动跳过空元素
const eachFlat = (arr = [], depth = 1) => {
const result = []; // 缓存递归结果
// 开始递归
(function flat(arr, depth) {
// forEach 会自动去除数组空位
arr.forEach((item) => {
// 控制递归深度
if (Array.isArray(item) && depth > 0) {
// 递归数组
flat(item, depth - 1)
} else {
// 缓存元素
result.push(item)
}
})
})(arr, depth)
// 返回递归结果
return result;
}
// for of 循环不能去除数组空位,需要手动去除
const forFlat = (arr = [], depth = 1) => {
const result = [];
(function flat(arr, depth) {
for (let item of arr) {
if (Array.isArray(item) && depth > 0) {
flat(item, depth - 1)
} else {
// 去除空元素,添加非 undefined 元素
item !== void 0 && result.push(item);
}
}
})(arr, depth)
return result;
}
方法二 巧用 reduce
// 使用 reduce 来解析第一层数组
const arr = [1, [[2, 3], 4],5]
const result = arr.reduce((acc, val) => acc.concat(val), []);
console.log(result);
// 输出: [1,[2,3],4,5]
// 对于多层级嵌套的数组, 这个时候就需要使用递归的思想来解决问题
const arr = [1, [[2, 3], 4],5]
const flatten = (arr, deep = 1) => {
if (deep <= 0) return arr;
return arr.reduce((res, curr) => res.concat(Array.isArray(curr) ? flatten(curr,
deep - 1) : curr), [])
}
console.log(arr, 3);
// 输出:[ 1, 2, 3, 4, 5, 6 ]
方法三 使用堆栈 stack 避免递归
思路:
- 把数组通过一个栈来维护
- 当栈不为空的时候循环执行处理
- pop()将栈尾出栈
- 如果出栈的元素是数组,就将该元素解构后每一元素进行入栈操作
- 出栈的元素不是数组就push进返回值res
- 反转恢复原数组的顺序
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flatten(arr) {
const stack = [...arr];
const res = [];
while (stack.length) {
// 使用 pop 从 stack 中取出并移除值
const next = stack.pop();
if (Array.isArray(next)) {
// 使用 push 送回内层数组中的元素,不会改动原始输入
stack.push(...next);
} else {
res.push(next);
}
}
// 反转恢复原数组的顺序
return res.reverse();
}
flatten(arr1);// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
方法四 while 循环+ some方法
思路
通过some来判断数组中是否有数组,通过while不断循环执行判断, 如果是数组的话可以使用 展开运算符...
... 每次只能展开最外层的数组,加上contact
来减少嵌套层数
function flatten(arr) {
while (arr.some(item=> Array.isArray(item))) {
console.log(...arr)
arr = [].concat(...arr)
console.log(arr)
}
return arr
}
console.log(flatten(arr));