Array.prototype.flat()
释义
flat
作为 JavaScript 中的数组方法,可以用于扁平化多维数组。其作用是将数组中的子数组“拉平”到指定的深度,变成一维数组。
词汇解释
- 形容词 (adj.):平的;水平的;平滑的;扁平的;枯燥的;平淡的;色彩单调的;不景气的;断然的;降音的;低于标准音高的;走了气的;电用完了的;瘪了的。
- 名词 (n.):公寓;一套房间;单元房;平面部分;低洼地;无障碍平地赛马季节;降半音;瘪了的轮胎;平面布景。
- 副词 (adv.):平躺地;断然;低于标准音高。
- 动词 (vi.):合住公寓。
参数
结构深度:控制扁平化的深度。即多少层嵌套的数组会被扁平化成一维数组。
使用示例
扁平化多维数组
// Array.prototype.flat() ES2019
// 示例:扁平化二维数组
const arr = [0, 1, [2, 3], 4, 5];
// 返回一个新的数组,将二维数组拍平
const newArr = arr.flat();
console.log(newArr === arr); // false
const arr1 = [0, 1, [1, 2, [3, 4], 5], 6];
// 默认参数为1,表示浅层扁平化
const newArr1 = arr1.flat(2);
console.log(newArr1); // [0, 1, 1, 2, 3, 4, 5, 6]
处理多维数组
扁平化所有层级的数组
通过设置Infinity
来扁平化至所有层级:
const arr1 = [0, 1, [1, 2, [3, 4], 5], 6];
// 使用 Infinity 实现完全扁平化
const newArr1 = arr1.flat(Infinity);
console.log(newArr1); // [0, 1, 1, 2, 3, 4, 5, 6]
负值深度
如果传入负值作为深度参数,将不会进行任何扁平化操作。
const arr1 = [0, 1, [1, 2, [3, 4], 5], 6];
// 传入负数深度值,数组不做扁平化处理
const newArr1 = arr1.flat(-2);
console.log(newArr1); // [0, 1, [1, 2, [3, 4], 5], 6]
字符串作为深度
传入字符串会被视为 NaN,因此不会进行任何扁平化操作。
const arr1 = [0, 1, [1, 2, [3, 4], 5], 6];
// 传入字符串 'a',将无法进行扁平化处理
const newArr1 = arr1.flat('a');
console.log(newArr1); // [0, 1, [1, 2, [3, 4], 5], 6]
数字字符串作为深度
数字字符串会被转换为 NaN
,因此不会执行扁平化操作。
const arr1 = [0, 1, [1, 2, [3, 4], 5], 6];
// 传入数字字符串 '3',该值转换为 NaN,不会进行扁平化
const newArr1 = arr1.flat('3');
console.log(newArr1); // [0, 1, [1, 2, [3, 4], 5], 6]
布尔值作为深度
布尔值 false
等同于 0,true
等同于 1。因此可以根据布尔值控制扁平化的层数。
const arr1 = [0, 1, [1, 2, [3, 4], 5], 6];
// false 等同于 0,不做任何扁平化
const newArr1 = arr1.flat(false);
console.log(newArr1); // [0, 1, [1, 2, [3, 4], 5], 6]
// true 等同于 1,执行一层扁平化
const newArr2 = arr1.flat(true);
console.log(newArr2); // [0, 1, 1, 2, [3, 4], 5, 6]
处理稀疏数组
flat
方法会自动剔除 empty
(稀疏数组中的空位)。
const arr1 = [1, , , , 2, , , 3, , 4, [2, [3], 2], 2, 32];
// 扁平化至所有层级,剔除空位
const newArr1 = arr1.flat(Infinity);
console.log(newArr1); // [1, 2, 3, 4, 2, 3, 2, 2, 32]
扁平化方法实现
浅扁平化
浅扁平化只会展开一层嵌套数组,常见的实现方式是使用 reduce
和 concat
。
// 通过 reduce + concat 实现浅扁平化
function shallowFlat(arr) {
return arr.reduce(function (prev, current) {
return prev.concat(current);
}, []);
}
// 使用扩展运算符实现简化版本
function shallowFlat(arr) {
return [].concat(...arr);
}
深度扁平化
使用 reduce
+ isArray
+ concat
+ 递归
递归处理每一层嵌套,直到达到指定的深度。
Array.prototype.deepFlat = function () {
var arr = this,
deep = arguments[0] !== Infinity ? arguments[0] >>> 0 : Infinity;
return deep > 0
? arr.reduce(function (prev, current) {
return prev.concat(Array.isArray(current) ? current.deepFlat(deep - 1) : current);
}, [])
: arr;
};
const arr1 = [1, , , , 2, , , 3, , 4, [2, [3], 2], 2, 32];
console.log(arr1.deepFlat(Infinity)); // [1, 2, 3, 4, 2, 3, 2, 2, 32]
使用 forEach
+ isArray
+ push
+ 递归
通过 forEach
遍历数组,递归调用处理每一层的嵌套。
Array.prototype.deepFlat = function () {
var arr = this,
deep = arguments[0] !== Infinity ? arguments[0] >>> 0 : Infinity,
res = [];
(function _(arr, deep) {
arr.forEach(function (item) {
if (Array.isArray(item) && deep > 0) {
_(item, deep - 1);
} else {
res.push(item);
}
});
})(arr, deep);
return res;
};
使用 for of
+ isArray
+ push
+ 递归
通过 for of
循环遍历每个元素,判断是否为数组并递归处理。
Array.prototype.deepFlat = function () {
var arr = this,
deep = arguments[0] !== Infinity ? arguments[0] >>> 0 : Infinity,
res = [];
(function _(arr, deep) {
for (var item of arr) {
if (Array.isArray(item) && deep > 0) {
_(item, deep - 1);
} else {
item !== void 0 && res.push(item); // 剔除空位
}
}
})(arr, deep);
return res;
};
使用栈(stack
)+ pop
+ push
通过栈的方式,逐步展开数组。
Array.prototype.deepFlat = function () {
var arr = this,
stack = [...arr],
res = [];
while (stack.length) {
const popItem = stack.pop();
if (Array.isArray(popItem)) {
stack.push(...popItem);
} else {
if (popItem != undefined) {
res.push(popItem);
}
}
}
return res.reverse();
};
const arr1