到目前为止,递归一直是我的难题。作为一项任务,我尝试使用递归从头开始编写代码。我写了这个函数来展平数组。
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
有时求值为{{1} }。
我想了解为什么会发生这种情况,我认为直接假设undefined
总是等于temp
就可以了。
答案 0 :(得分:0)
我不知道是否可以在这里回答我自己的问题,但是我找到了答案,并且我不想让这个问题没有答案。
通过运行代码可以看到,在else块内,bar的求值正确,但是当我返回它时,变量temp有时立即求值为未定义。
我想了解为什么会发生这种情况,我认为直接假设temp总是等于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));
这不是最优雅的方法,但是可以完成工作。
答案 1 :(得分:0)
尝试以下代码,这只是对答案的修改。
我认为这将是更好的方法,而且您会更清楚地了解它。
请参阅代码中的注释,以了解进行这些更改的原因。
// 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
答案 2 :(得分:0)
您可以利用某些语言构造或本机方法取消嵌套数组的作用:
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]));
答案 3 :(得分:0)
将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));