开门见山,什么是数组扁平化呢,就是把一个多维数组变为一维数组。如下就是一个5维数组。
不考虑兼容的情况下,ES6中提供了Array.prototype.flat处理.
flat(depth) 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
let arr = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10
]
/*ES6方法直接实现*/
// arr=arr.flat(Infinity); // 完全扁平化
// [
// 1, 2, 2, 3, 4, 5, 5,
// 6, 7, 8, 9, 11, 12, 12,
// 13, 14, 10
// ]
toSting方法,转化为字符串,再拼接为数组,需要处理字符串转数字类型。
let arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];
arr=arr.toString() // 1,2,2,3,4,5,5,6,7,8,9,11,12,12,13,14,10
arr = arr.toString().split(",") // ['1', '2', '2', '3','4', '5', '5', '6','7', '8', '9', '11','12', '12', '13', '14','10']
arr = arr
.toString()
.split(",")
.map((item) => parseFloat(item)); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]
console.log(arr);
转化为JSON字符串,需要处理掉[和]
arr=JSON.stringify(arr).replace(/(\[|\])/g,'').split(',').map(item=>parseFloat(item));
创建一个空容器,循环数组中的每一项,如果当前项不是数组就存进去,是数组就递归。
while(arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr)
}
// [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]
自己递归处理,首先初始化一个空数组 result 用于存储扁平化后的结果,同时创建一个 _this 变量来引用数组对象本身。
定义了一个递归函数 fn,用于遍历数组的每一项并将其添加到 result 中。如果遍历到的项是数组,则递归调用 fn 进一步处理内部嵌套数组。
最后,fn(_this) 将会从原始的数组 _this 开始进行扁平化操作。
(function () {
function myFlat() {
let result = [],
_this = this;
//=>循环ARR中的每一项,把不是数组的存储到新数组中
let fn = (arr) => {
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (Array.isArray(item)) {
fn(item);
continue;
}
result.push(item);
}
};
fn(_this);
return result;
}
Array.prototype.myFlat = myFlat;
})();
arr = arr.myFlat();
console.log(arr);
那么如何实现控制深度的扁平化呢?
接受一个额外的参数 depth,用于控制扁平化的深度。递归函数 fn 会检查当前递归的深度是否小于 depth,如果小于则继续递归展开子数组,否则直接将子数组的元素添加到结果中。
(function () {
function myFlat(depth = 1) {
let result = [],
_this = this;
let fn = (arr, currDepth) => {
for (let i = 0; i < arr.length; i++) {
let item = arr[i];
if (Array.isArray(item) && currDepth < depth) {
fn(item, currDepth + 1);
} else {
result.push(item);
}
}
};
fn(_this, 1);
return result;
}
Array.prototype.myFlat = myFlat;
})();
arr = arr.myFlat(2);
[1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, Array(3), 10]
非递归方式实现扁平化,使用栈
- 使用一个栈(
stack数组)来进行迭代。初始时,将原数组_this的元素都复制到栈中。 - 进入循环,不断从栈中弹出元素。如果弹出的元素是数组,将其元素依次推入栈中,以便后续继续处理嵌套数组。
- 如果弹出的元素不是数组,将其添加到结果数组
result中。 - 循环结束后,由于元素是从栈的尾部弹出的,为了保持原有的顺序,使用
reverse()方法将结果数组进行翻转。
(function () {
function myFlat() {
let result = [],
_this = this;
let stack = [..._this];
while (stack.length) {
let item = stack.pop();
if (Array.isArray(item)) {
stack.push(...item);
} else {
result.push(item);
}
}
return result.reverse();
}
Array.prototype.myFlat = myFlat;
})();
arr = arr.myFlat();
console.log(arr); // [1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 9, 11, 12, 12, 13, 14, 10]