Javascript中产生无限循环的递归函数

Recursion function yielding infinite loop in Javascript

本文关键字:递归函数 无限循环 Javascript      更新时间:2023-09-26

我在使用递归函数生成一个简单的表时遇到了一些主要问题。我的目标是在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(几乎相同,但更混乱,因为它有很多控制台)。日志帮助我调试)- http://jsfiddle.net/wmkNe/206/

你要做的是数组递归。这将遍历paras变量中的所有数组。

我已经更新了你的小提琴

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" 316ss接地","2a71/8"6" 316ss接地","3a71/8"6" 316ss接地","1b71/8"6" 316ss接地","2b71/8"6" 316ss接地",…]

看着这个,我认为这就像在基数系统中使用不同的基数和每个位置的符号计数:

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", ...]