【问题标题】:Recursion function yielding infinite loop in Javascript递归函数在Javascript中产生无限循环
【发布时间】:2016-10-25 13:58:46
【问题描述】:

我在使用递归函数生成简单表时遇到了一些重大问题。我的目标是在 HTML 中生成一个表格,为我的子数组中每个可能的元素组合输出不同的行:

var paras = [
 [1, 2, 3],
 ["a", "b", "c"],
 //[7, 8, 9], //WARNING!!! UNCOMMENTING THIS LINE WILL RESULT IN AN INFINITE LOOP
 //['1/8"', '3/16"', '1/4"'],
 //['6"', '12"', '18"'],
 //["316SS"],
 //["Grounded", "Ungrounded", "Exposed"],
];

例如,在上面的数组中,我想生成以下内容:

1a7
1a8
1a9
1b7
1b8
1b9
1c7...
3c9

最终我希望将其输出到 HTML 中的表格中,但现在我所关心的基本上是尽我所能生成该模式。

现在是最难的部分。我不能使用嵌套的 for 循环。将 3 个循环相互嵌套很容易,每个循环从 1 到特定子数组的长度,但是当我有 4 个子数组、10 个或 1000 个子数组时呢?我希望代码独立于如何有多少个子数组,每个子数组有多少个变量。

var numcats = paras.length;
var retStack = [];
var retQ = [];



function genTable(array1) {
  if (array1.length == 1) { //if there is only 1 sub-array (base case)
    if (array1[0].length == 1) { //if that array contains only 1 element
      retStack.push(array1[0][0]);
      return retStack;
    } else {
      var temp = array1;
      var item = temp[0].pop();
      retStack = genTable(temp);
      retStack.push(item);
      return retStack; //returns 1 2 3 when there is only 1 sub array
    }
  } else {
    var tempParas = array1;
    var topArray = tempParas.pop();
    var permQ = genTable(tempParas);
    for (i = 0; i < topArray.length; i++) {
      var tempQ = [];
      var tempQ = permQ;
      while (tempQ.length >= 1) {
        retQ.push(topArray[i]);
        for (j = 0; j < tempParas.length; j++) {
          retQ.push(tempQ.pop());
        }
      }
    }
    return retQ; //returns a 3 a 2 a 1 when there are 2 sub-arrays
  }
}

console.log(genTable(paras))

我的问题:

  • 当我有 2 个子数组(如上所示)时,返回值为 3 a 2 a 1。我也许可以通过使用 shift 而不是 pop 来解决倒序问题?但是为什么不继续b和c。
  • 当我有 3 个或更多子数组时,我会陷入无限循环(我相信 while 循环不会中断,因为条件中的变量定义不正确?也许..?

如果您想查看我的实际代码,这是我的 jsfiddle(几乎相同,但更混乱,因为它有很多 console.logs 可以帮助我调试)-http://jsfiddle.net/wmkNe/206/

【问题讨论】:

    标签: javascript arrays recursion infinite-loop


    【解决方案1】:

    您正在尝试做的是数组递归。这将遍历 paras 变量中的所有数组。

    我已经更新了你的fiddle

    var paras = [
      [1, 2, 3],
     ["a", "b", "c"],
     [7, 8, 9], //WARNING!!! UNCOMMENTING THIS LINE WILL RESULT IN AN INFINITE LOOP
     ['1/8"', '3/16"', '1/4"'],
     ['6"', '12"', '18"'],
     ["316SS"],
     ["Grounded", "Ungrounded", "Exposed"],
    ];
    
    function arrayRecursion(paras) {
      if (paras.length == 1) 
        return paras[0];
    
      var results = [];
      var allValues = arrayRecursion(paras.slice(1));
      for (var i = 0; i < allValues.length; i++) {
        for (var j = 0; j < paras[0].length; j++) {
          results.push(paras[0][j] + allValues[i]);
        }
      }
      return results;    
    }
    
    console.log(arrayRecursion(paras));
    

    这将返回结果为: ["1a71/8"6"316SSGrounded"、"2a71/8"6"316SSGrounded"、"3a71/8"6"316SSGrounded"、"1b71/8"6"316SSGrounded"、"2b71/8"6"316SSGrounded" ,...]

    【讨论】:

    • 哇,你的要简单得多,而且几乎完美。出于某种原因,它不适用于我的第四个阵列。此外,当一行中有 2 个数组都用数字填充时,它也不起作用,因为它将数字加在一起,而不是连接它们。我是否必须将所有元素定义为数组中的字符串?或者有什么办法可以将它们转换为函数中的字符串?
    • 为了防止数字被添加,您可以强制将值解析为字符串... var allValues = arrayRecursion(paras.slice(1).toString());
    • 会生成 ["1a,b,c,7,8,9", "2a,b,c,7,8,9", "3a,b,c,7,8 ,9"] 其中只有每个组的第一个元素遵循模式 =/,除非我做错了
    • 你说的很对。我将在几分钟后再看一下该方法。目前正在开会。
    • 我已经分叉了你原来的小提琴,现在一切似乎都按预期工作了。让我知道这是否仍然行为不端,我会再看看它。 jsfiddle.net/98oL12tk/1
    【解决方案2】:

    看着这个,我想这就像在一个基础系统中使用不同的基础和每个位置的符号进行计数:

    function getCounter(arrSymbols) {
      const arrSymbolsReversed = arrSymbols.reverse();
      return n => arrSymbolsReversed
        .reduce((o, s) => ({str:  s[o.n % s.length]+o.str, n: Math.floor(o.n / s.length)}), {str:"",n:n})
        .str;
    }
    var count = getCounter([['1','2','3'],['a','b','c'],['7','8','9']]);
    _.range(0,27).map(count); //=> ["1a7", "1a8", ...]
    

    【讨论】:

    • 基本上,是的,这只是一个计数问题,每个数字的基数不同。抱歉,我对这些东西不是很有经验,但是 _.range 行有问题,我应该填写那个空白吗?我也希望它适用于所有尺寸,所以我必须通过将数组的所有长度相乘来生成 27 吗?
    • @MatthewSirkin 不,它是下划线。 _.range(0,27) 是创建数组[0...26] 的下划线库函数。
    猜你喜欢
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 2016-10-06
    • 2015-12-25
    相关资源
    最近更新 更多