方式1:递归法
思路: 创建一个新数组result, 遍历源数组的每一项,判断该项是否为一个数组,如果是一个数组,则递归处理该项数组,如果不是数组,则把该项push到result中,最终将result返回即可。
function flat1(source) {
if (!source.length) return [];
const result = [];
function rec(arr) {
arr.forEach(el => {
//el为数组,递归
if (Array.isArray(el) && el.length) {
rec(el);
//el不为数组
} else {
result.push(el);
}
});
}
rec(source);
return result;
}
方式2:栈方法
思路: 利用栈
处理,每次出栈的元素叫做current,current如果为数组,那么遍历该数组,并把数组的每一项推到栈顶,如果不是数组,则把该项push到result中,最终将result返回即可。
function flat2(source) {
if (!source.length) return [];
const result = [];
const stack = [source];
while (stack.length) {
const current = stack.shift();
if (Array.isArray(current) && current.length) {
// 方式1:需要反转
current.reverse().forEach(el => {
stack.unshift(el);
});
// 方式2:优雅写法
// stack.unshift(...current);
} else {
result.push(current);
}
}
return result;
}
方式3:利用字符串(该方法要求数组的元素为基本类型)
思路:
JS数组转字符串会有一个特点,例如 [0, 1, 2, [3, 4], 5] 转为字符串之后变成 '0, 1, 2, 3, 4, 5'。
注意如果最终每个元素都为String
类型,根据需求决定是否要转Number
。
function flat3(source) {
if (!source.length) return [];
return str.split(",").map(el => el * 1); // 注意el转为数字
//正则替换的思路亦可
//const str = JSON.stringify(source);
//return str.replace(/(\[|\])/g, "").split(",").map(el => el * 1);
}
方式4:利用原生flat方法
思路: 利用JS数组的flat
方法,该方法有一个特点,就是每执行都会帮数组降一维,就是 [0, [1, 2, [3, 4]], 5] 执行flat之后变成 [0, 1, 2, [3, 4], 5] , [0, 1, 2, [3, 4], 5] 再执行flat之后变成 [0, 1, 2, 3, 4, 5]。
根据这个思路,可以执行flat(Infinity)
,从而实现数组的扁平化。
function flat4(source) {
return result = source.flat(Infinity);;
}
方式5:利用扩展运算符
思路: 用while
重复解构,直至数组的每一项都不为数组。
//该方法会改变原数组,可以自行深拷贝再做处理
function flat5(source) {
while (source.some(Array.isArray)) {
source = [].concat(...source);
}
return source;
}
测试
说明: 方法3要求数组的元素为基本类型,数组为引用类型的请自行校验,本人校验结果均无误(有误请在评论区留代码,感谢)。
console.log(flat1([0, [1, 2, [3, 4]], 5])); //[0, 1, 2, 3, 4, 5]
console.log(flat2([0, [1, 2, [3, 4]], 5])); //[0, 1, 2, 3, 4, 5]
console.log(flat3([0, [1, 2, [3, 4]], 5])); //[0, 1, 2, 3, 4, 5]
console.log(flat4([0, [1, 2, [3, 4]], 5])); //[0, 1, 2, 3, 4, 5]
console.log(flat5([0, [1, 2, [3, 4]], 5])); //[0, 1, 2, 3, 4, 5]