递归函数后如何初始化全局数组

时间:2019-07-02 11:21:30

标签: javascript arrays recursion

在调用steamrollArray函数后,我很难重新初始化数组arrRolled。 该函数的目标是返回一个包含所有元素且没有嵌套数组的数组。

例如:[1,[2],[3,[[4]]]] ===> [1,2,3,4]

当我尝试在返回abc之前初始化arrRolled时,即使abc声明作为arrRolled的副本之后出现了声明“ arrRolled = []”,但abc仍作为空数组返回“ abc = arrRolled.slice( )”



var arrRolled=[];

function steamrollArray(arr) {
  for (let i=0; i<arr.length; i++) {
    //console.log()
    if (arr[i] instanceof Array) {
        let j = i;
        steamrollArray(arr[j]);
        continue;
    } else {
      //console.log("else:" + arr[i]);
      arrRolled.push(arr[i]);
      //console.log(arrRolled);
      continue;
  }
  }
  var abc = arrRolled.slice();
    //arrRolled=[];
    return abc;
}

预期结果:

console.log(steamrollArray([1, [2], [3, [[4]]]])) // [1,2,3,4]
console.log(steamrollArray([[["a"]], [["b"]]]));  //["a", "b"]

实际结果:

console.log(steamrollArray([1, [2], [3, [[4]]]])) // [1,2,3,4]
console.log(steamrollArray([[["a"]], [["b"]]]));  //[1,2,3,4,a,b]

3 个答案:

答案 0 :(得分:0)

每次调用steamrollArray时,都必须使arrRolled无效。

steamrollArray已经涵盖了对var arrRolled=[];的第一个呼叫,但是其他任何呼叫都没有。

答案 1 :(得分:0)

<!DOCTYPE html>
<html>
<head>

</head>

<body>


<script>
var Trouble=[1, [2], [3, [[4]]]];
var Trouble2=[[["a"]], [["b"]]];






function Turn(CharZ){
	var Result=[];
	for(var i=0;i<CharZ.length;i++){
		if(!(Array.isArray(CharZ[i]))){
			Result.push(CharZ[i]);
		}else{
			Result = Result.concat(Turn(CharZ[i]));
		}
	}
	return Result;
}
var NotTrouble=Turn(Trouble);
console.log(NotTrouble);
document.body.innerHTML = NotTrouble;

var NotTrouble2=Turn(Trouble2);
console.log(NotTrouble2);
document.body.innerHTML +="<br>";
document.body.innerHTML += NotTrouble2;






</script>

</body>
</html>

这是简单的答案

答案 2 :(得分:0)

解决此问题的一种方法是在每次启动呼叫时都更新您的助手,但这很麻烦并且演示了全局变量的一些问题。由于您需要在每次递归调用之间保持此状态,因此不能简单地在函数开始时对其进行初始化。但是,完成此操作的一种方法是将其作为默认参数添加到函数中,然后将当前值传递给递归调用。看起来像这样:

function steamrollArray (arr, arrRolled = []) {
  for (let i = 0; i < arr .length; i++) {
    if (arr [i] instanceof Array) {
        let j = i;
        steamrollArray (arr [j], arrRolled);
        continue;
    } else {
      arrRolled .push (arr [i]);
      continue;
    }
  }
  var abc = arrRolled .slice ();
  return abc;
}

console.log (steamrollArray ([1, [2], [3, [[4]]]])) // [1,2,3,4]
console.log (steamrollArray ([[["a"]], [["b"]]]));  //["a", "b"]

但是,这里有很多无关的代码。让我们看看是否可以简化它。取出不必要的continue语句,对仅在声明后才使用的局部变量进行内联,并删除现在冗余的slice调用,我们得到了一些更整洁的东西:

function steamrollArray (arr, arrRolled = []) {
  for (let i = 0; i < arr.length; i++) {
    if (arr [i] instanceof Array) {
        steamrollArray (arr [i], arrRolled);
    } else {
      arrRolled .push (arr [i]);
    }
  }
  return arrRolled;
}

但是,使用一些ES6功能,我们可以变得更加干净:

const steamrollArray = (arr) => arr .reduce (
  (a, x) => [...a, ...(Array .isArray (x) ? steamrollArray (x) : [x])],
  []
)

但是,除非这不是一项学习练习,否则所有这些恐怕都涉及太多的代码。因为此功能实际上是built into现代JS引擎(而不是IE或Edge)。所以,实际上您需要的只是

const steamrollArray = (arr) => arr.flat(Infinity)