[英]flattening an array with recursion
到目前为止,递归一直是我的难题。 作为一项任务,我尝试使用递归从头开始编写代码。 我写了这个函数来展平数组。
function foo(item) { if (item instanceof Array) { for (let ii of item) { foo(ii); } } else { let bar = item; console.log(bar); return bar; } } function arrFlatten(arr) { let result = []; for (let i of arr) { let temp = foo(i); console.log(temp); result.push(temp); } console.log(result); return result; } let bar = [1, [2], [3, [[4]]]]; arrFlatten(bar);
我放了2 console.log()
一个正在打印变量bar
,另一个正在打印变量temp
。
通过运行代码可以看到,在else
块中, bar
求值正确,但是当我返回它时,变量temp
有时有时求值为undefined
。
我想了解为什么会发生这种情况,我认为直接假设temp
总是等于bar
。
我不知道是否可以在这里回答我自己的问题,但是我找到了答案,我也不想离开这个问题。
通过运行代码可以看到,在else块内,bar的求值正确,但是当我返回它时,变量temp有时立即求值为undefined。
我想了解为什么会这样,我认为假设温度始终等于bar是很直接的。
temp
有时返回undefined
的原因是因为没有考虑到所有javascript函数都返回undefined
除非另有说明。
那些undefined
的事正在发生
function foo(item) {
if (item instanceof Array) {
for (let ii of item) {
foo(ii);
}
} else {
let bar = item;
console.log(bar);
return bar;
}
}
每次for loop
结束且函数结束时,函数将返回undefined
。
知道这一点,我不得不像这样重写代码。
function foo(item, arr=[]) {
let result;
if (item instanceof Array) {
for (let ii of item) {
result = foo(ii, arr);
}
} else {
arr.push(item);
return arr;
}
return result;
}
let bar = [1, [2], [3, [[4, 5], 6], 7], 8];
console.log(foo(bar));
这不是最优雅的方法,但是可以完成工作。
试试下面的代码,它只是对答案的修改。
我认为这将是更好的方法,并且您会更清楚地了解它。
请参阅代码中的注释,以了解我为什么进行这些更改。
// You don't need a 2nd argument, so remove it
function flatten(items){
let result = [];
// for loop should be outside the if statement
for(let item of items){
if(item instanceof Array){
// flatten recursively, returned array will contain flattened subarray
var flattenedItems = flatten(item);
for(let flattenedItem of flattenedItems){
// Since flattenedItems are returned by
// a recursive call to this function itself,
// it is guaranteed that all the elements of
// flattenedItems will already flatted
// So, its safe to directly push it to result
result.push(flattenedItem);
}
}
else{
result.push(item);
// do not return here as I moved for loop out of the if statement
}
}
return result;
}
console.log(flatten([1, [2], [3, [[4, 5], 6], 7], 8]));
// 1, 2, 3, 4, 5, 6, 7, 8
您可以利用某些语言构造或本机方法取消嵌套数组:
const a = [[1,2],[3,4]];
使用价差运算符:
[...a[0], ...a[1]];
//=> [1,2,3,4]
使用concat
:
[].concat(a[0], a[1]);
//=> [1,2,3,4]
使用flatMap
:
a.flatMap(x => x);
//=> [1,2,3,4]
您可以在递归函数中将相同的原理应用于任何深度的嵌套数组:
注意:IE / Edge不支持flatMap
const flatten = arr => arr.flatMap(x => Array.isArray(x) ? flatten(x) : x); console.log(flatten([1, [2], [3, [[4]]]])); console.log(flatten([1, [2], [3, [[4, 5], 6], 7], 8]));
将undefined
打印到控制台的原因是,并非foo
函数的所有分支都具有返回值。 如果命中if语句,它将返回undefined
(因为未指定返回值)。
您可以使用Array.prototype.flat
简化您的功能(请记住,它的支持有限)。 flat
不会无限地变平坦。 但是,文档中提到了Alternatives ,从中可以递归地变平。
//to enable deep level flatten use recursion with reduce and concat var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]]; function flattenDeep(arr1) { return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []); } flattenDeep(arr1);// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
function flattenDeep(arr) { return arr.reduce( (acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), [] ); } const bar = [1, [2], [3, [[4]]]]; console.log(flattenDeep(bar));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.