拍平数组flat

# Array.prototype.flat()
const animals = ["🐷", ["🐶", "🐂"], ["🐎", ["🐑", ["🐲"]], "🐛"]];
// 不传参,默认拉平一层
animals.flat();
// [ '🐷', '🐶', '🐂', '🐎', [ '🐑', [ '🐲' ] ], '🐛' ]
// 传一个整数参数,整数即拉平的层数
animals.flat(2);
// [ '🐷', '🐶', '🐂', '🐎', '🐑', [ '🐲' ], '🐛' ]
// Infinity 作为参数,无论嵌套多少层,都转为一维数组
animals.flat(Infinity);
// ['🐷', '🐶', '🐂', '🐎', '🐑', '🐲', '🐛']
// 传入 <= 0的整数 返回原数组
animals.flat(0);
animals.flat(-10);
// ["🐷", ["🐶", "🐂"], ["🐎", ["🐑", ["🐲"]], "🐛"]]
// 如果原数组有空位,flat()方法会跳过空位。
["🐷", "🐶", "🐂", "🐎", ,].flat();
// ["🐷", "🐶", "🐂", "🐎"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Array.prototype.flat() 特性
- 用于将嵌套数组拉平,变成一维数组。该方法返回一个新数组,对原数组没影响
- 不传参,默认拉平一层;传入一个整数,表示拉平的层数
- 传入 <= 0 的整数,返回原数组
- Infinity 关键字作为参数,无论嵌套多少层,都转为一维数组
- 若原数组有空位,会跳过空位
# 实现一个数组拍平flat函数
# 实现思路
- 遍历数组的每一个元素
- 判断元素是否是数组
- 将数组的元素展开一层
const arr = [1, 2, 3, 4, [1, 2, 3, [1, 2, 3, [1, 2, 3]]], 5, "string", { name: "弹铁蛋同学" }];
// concat + 递归
function flat(arr) {
let arrResult = [];
arr.forEach(item => {
if (Array.isArray(item)) {
arrResult = arrResult.concat(arguments.callee(item)); // 递归
// 或者用扩展运算符
// arrResult.push(...arguments.callee(item));
} else {
arrResult.push(item);
}
});
return arrResult;
}
flat(arr)
// [1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, "string", { name: "弹铁蛋同学" }];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 用 reduce 实现 flat 函数
const arr = [1, 2, 3, 4, [1, 2, 3, [1, 2, 3, [1, 2, 3]]], 5, "string", { name: "弹铁蛋同学" }]
const flat = arr => {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flat(cur) : cur);
}, []);
};
1
2
3
4
5
6
7
2
3
4
5
6
7
# 用栈的思想实现 flat 函数
function flat(arr) {
const result = [];
const stack = [].concat(arr); // 将数组元素拷贝至栈,直接赋值会改变原数组
while (stack.length !== 0) {
const val = stack.pop();
Array.isArray(val) ? stack.push(...val) : result.unshift(val);
}
return result;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 通过传入整数参数控制拉平层数
function flat(arr, num = 1) {
return num > 0 ? arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flat(cur, num - 1) : cur), []) : arr.slice();
}
1
2
3
2
3
# 使用 Generator 实现 flat 函数
function* flat(arr, num = 1) {
for (const item of arr) {
if (Array.isArray(item) && num > 0) {
yield* flat(item, num - 1);
} else {
yield item;
}
}
}
// 调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象
// 即遍历器对象,需用一次扩展符运算得到结果
console.log([...flat(arr)]);
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 实现在原型链上重写flat函数
Array.prototype.fakeFlat = function (num = 1) {
if (!Number(num) || Number(num) < 0) return this;
let arr = this.concat();
while (num > 0) {
if (arr.some(x => Array.isArray(x))) {
arr = [].concat.apply([], arr);
console.log(arr);
} else {
break;
}
num--;
}
return arr;
};
console.log(arr.fakeFlat(Infinity));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 考虑数组空位情况
ES5大多数数组方法对空位的处理都会选择跳过空位:forEach()、filter()、reduce()、every()、some()
const arr = [1, [3, 4], , ,];
// reduce + 递归
Array.prototype.fakeFlat = function(num = 1) {
if (!Number(num) || Number(num) < 0) {
return this;
}
let arr = [].concat(this);
return num > 0
? arr.reduce(
(pre, cur) =>
pre.concat(Array.isArray(cur) ? cur.fakeFlat(--num) : cur),
[]
)
: arr.slice();
};
arr.fakeFlat()
// [1, 3, 4]
// foEach + 递归
Array.prototype.fakeFlat = function(num = 1) {
if (!Number(num) || Number(num) < 0) {
return this;
}
let arr = [];
this.forEach(item => {
if (Array.isArray(item)) {
arr = arr.concat(item.fakeFlat(--num));
} else {
arr.push(item);
}
});
return arr;
};
arr.fakeFlat()
// [1, 3, 4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# ES5 与 ES6 对数组空位的处理
ES5在多数情况下回忽略空位
forEach()、filter()、reduce()、every()和some()都会跳过空位map()会跳过空位,但会保留这个值join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串
ES6明确将空位转为undefined
entries()、keys()、values()、find()和findIndex()会将空位处理成undefinedfor...of循环会遍历空位fill()会将空位视为正常的数组位置copyWithin()会连空位一起拷贝- 扩展运算符也会将空位转为
undefined Array.from方法会将数组的空位转为undefined
上次更新: 2022/09/02, 17:10:06