递归和循环 - 超出最大调用堆栈

时间:2014-04-26 14:36:02

标签: javascript recursion

我正在尝试构建一个将字符串中的所有数字相加的函数...例如,'dlsjf3diw62'最终会为65.

我试图变得聪明并将一个递归函数放在一起:

function NumberAddition(str) { 
  var numbers='1234567890';
  var check=[];
  str=str.split[''];
  function recursive(str,check) {
    if (str.length==0)
      return check;
    else if (numbers.indexOf(str[0])>=0)
    {
      for (i=0;i<str.length;i++){
        if (numbers.indexOf(str[i])<0)
          check.push(str.slice(0,i));
        str=str.slice(i);
        return recursive(str,check);
      }
    }
    else
      str.shift();
    return recursive(str,check);
  }

你会看到我正在尝试将我的数字作为名为check的数组中的数组返回。不幸的是,我超出了最大调用堆栈大小,我不知道为什么!递归确实有一个基本情况!它结束一旦str不再有任何内容。为什么这不起作用?有什么我想念的吗?

- 将会

2 个答案:

答案 0 :(得分:2)

使用正则表达式,您可以使用更简单的解决方案实现相同的目的,如下所示:

var str = 'dlsjf3diw62';
var check = str.match(/\d+/g); // this pattern matches all instances of 1 or more digits

然后,要对数字求和,您可以这样做:

var checkSum = 0;
for (var i = 0; i < check.length; i++) {
    checkSum += parseInt(check[i]);
}

或者,更紧凑:

var checkSum = check.reduce(function(sum, num){ return sum + parseInt(num) }, 0);

答案 1 :(得分:1)

你的递归不起作用的原因是你输入for循环,因为你找到了一个数字,但数字仍然是字符串的结尾。如果发生这种情况,return循环内的for永远不会发生,循环结束。之后,.shift()会发生,因为它位于else分支中,因此您将返回重新处理相同的字符串。

您不应该以这种方式解决这个特定问题,但代码是return内部if语句后跟else语句的反模式的一个很好的例子。如果它看起来像这样,你的代码会更清晰(并且可以工作):

function recursive(str, check) {
    if (str.length == 0)
        return check;

    if (numbers.indexOf(str[0]) >= 0) {
        // Find the end of the string of digits, or
        // the end of the whole thing
        for (var i = 0; i < str.length && numbers.indexOf(str[i]) >= 0; i++);

        check.push(str.slice(0, i));
        str = str.slice(i);
        return recursive(str, check);
    }

    // A non-digit character
    str.shift();
    return recursive(str, check);
}

在该版本中,没有else个子句,因为两个if子句总是涉及returnfor循环更改为查找后续切片的正确值“i”。

编辑 - 有一点不能解决的问题是您将数组推入“检查”列表。也就是说,子串“62”将被推送为数组["6", "2"]。这不是一个大问题;它通过在正确的位置添加.join()来解决。