实现一个数组扁平化的函数 flatten
更多描述
flatten
模拟Array.prototype.flat
实现,默认展开一层,可传递参数用以展开多层
// [1, 2, 3, 4, [5, 6]]
flatten([1, 2, 3, [4, [5, 6]]]);
// [1, 2, 3, 4, 5, 6]
flatten([1, 2, 3, [4, [5, 6]]], 2);
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 451
Author 回答者: shfshanyue
在 ES2019 之前,可通过 reduce
+ concat
实现,由于 Array.prototype.concat
既可以连接数组又可以连接单项,十分巧妙
const flatten = (list) => list.reduce((a, b) => a.concat(b), []);
一个更简单的实现方式是 Array.prototype.concat
与 ...
运算符
const flatten = (list) => [].concat(...list);
如果要求深层数组打平,则如下实现
const flatten = (list) =>
list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
如果要求如同原生 API Array.prototype.flat
一致的 API,可传入可扁平的深度。代码可见 【Q443】实现一个数组扁平化的函数 flatten
function flatten(list, depth = 1) {
if (depth === 0) return list;
return list.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b, depth - 1) : b),
[],
);
}
在 ES2019 之后,可通过 Array.prototype.flat
直接实现!
Author 回答者: reveriesMeng
您好作者,您的实现方式最多只能降维一层深度。
const flatten = (list) =>
list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
不仅如此,ES2019的flat还支持传入depth来降维指定的深度。
Author 回答者: shfshanyue
@reveriesMeng 好的
Author 回答者: demon-zhonglin
const flatten = (arr, d = 1) => d > 0 ? arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatten(val, d - 1) : val), []) : arr.slice()
Author 回答者: haotie1990
function flat(array, depth = Number.MAX_VALUE) {
let result = [...array];
while (result.some((i) => Array.isArray(i) && depth > 0)) {
// 注意concat方法的参数valueN,即可是数值也可以是数组,当时数组时存在隐形的展开操作
// concat方法不改变原数组,返回一个新数组
result = [].concat(...result);
depth--;
}
return result;
}
Author 回答者: shfshanyue
@haotie1990 原生 API 默认是 1,当然这个题目我也没有规定,不过 depth 用 MAX_SAFE_INTEGER 或者 Infinity 好一些?
而且该 API 也不涉及对数组自身的操作,应该无需 [...array]
Author 回答者: illumi520
function flatten(arr) {
return arr.reduce((result, item)=> {
return result.concat(Array.isArray(item) ? flatten(item) : item);
}, []);
}
Author 回答者: illumi520
function flatten(arr) { return arr.toString().split(’,‘).map(function(item) { return Number(item); }) }
Author 回答者: 3fuyang
一种使用迭代器的实现:
const flatten = function(target, depth = 1) {
const copy = [...target]
for(let i = 0; i < depth; ++i){
const iter = copy[Symbol.iterator]()
let item = null
for(item = iter.next(); !item.done; ){
// 注意:迭代器并不与可迭代对象某个时刻的快照绑定,而仅仅是用游标来记录遍历可迭代对象的历程,
// 如果可迭代对象在迭代期间被修改了,那么迭代器也会反映相应的变化
if(Array.isArray(item.value)){
const temp = [...item.value]
let size = temp.length
for(let j = 0; j < size; ++j){
item = iter.next()
}
copy.splice(copy.indexOf(item.value), 1, ...temp)
}else{
item = iter.next()
}
}
/* for(let item of copy){
if(Array.isArray(item)){
const temp = [...item]
copy.splice(copy.indexOf(item), 1, ...temp)
}
} */
}
return copy
}
Author 回答者: Vi-jay
支持depth为0
function flatten(arr = [], depth = 1) {
return arr.reduce(
(acc, cur) =>
acc.concat(
Array.isArray(cur) && depth > 0 ? flatten(cur, --depth) : [cur],
),
[],
);
}
Author 回答者: bldf
基于递归实现,不用 Array.concat
Array.prototype.myFlat = function (this: any[], depth: number = 1) {
const myFlat = (
arr: any[],
flatLength = 1,
resultArray = [] as any[],
forEachCount = 0,
) => {
arr.forEach((d: any) => {
if (
Array.isArray(d) &&
(flatLength === -1 || forEachCount < flatLength)
) {
myFlat(d, flatLength, resultArray, forEachCount + 1);
} else {
resultArray.push(d);
}
});
return resultArray;
};
return myFlat(this, depth);
};