简体   繁体   中英

When many for loops are used in Javascript, output is undefined

As shown at https://jsfiddle.net/LBMF_1/gacLzLnn/ , I have code that ostensibly generates all the possible permutations of 8 digits, using for loops within for loops.( At end of question ) My code seems to be correct in syntax, as both JSHint and the in-chrome console are free of errors. Is this my error, or is this a common problem caused by JS? It's probably the former as it seems that this should work Bonus Points: What other ways could be used to avoid the nested for loops? You don't know how much I am thankful for any help. Also, what is up with Stack Overflow and new paragraphs? The code is here, and it appears to me that when run should stick a really long list of numbers in the console, but instead lots of "undefined"'s appear.

var generator = function() {
  listofavailable = listofavailablereset;
  fullarray = [];


  for (i = 7; i > 0; i--) {
    numgen = "";
    inum = listofavailable[i];
    listofavailable.splice(i, 1);
    numgen = inum;
    for (v = 6; v > 0; v--) {
      vnum = listofavailable[v];
      listofavailable.splice(v, 1);
      numgen = numgen.concat(vnum);
      console.log(numgen);
      for (c = 5; c > 0; c--) {
        cnum = listofavailable[c];
        listofavailable.splice(c, 1);
        numgen = numgen.concat(cnum);
        for (g = 4; g > 0; g--) {
          gnum = listofavailable[g];
          listofavailable.splice(g, 1);
          numgen = numgen.concat(gnum);
          for (k = 3; k > 0; k--) {
            knum = listofavailable[k];
            listofavailable.splice(k, 1);
            numgen = numgen.concat(knum);
            for (b = 2; b > 0; b--) {
              bnum = listofavailable[b];
              listofavailable.splice(b, 1);
              numgen = numgen.concat(bnum);
              for (j = 1; j > 0; j--) {
                jnum = listofavailable[j];
                listofavailable.splice(j, 1);
                numgen = numgen.concat(jnum);
                fullarray = fullarray + numgen;
              }
            }
          }
        }
      }
    }
  }

};

Here's a modified implementation based on your fiddle. Note that the digits '0' and '5' are missing from your example, I'm not sure if this is intended.

var listofavailable = ['1', '2', '3', '4', '6', '7', '8', '9'];
var fullarray;

var generator = function() {
  fullarray = [];
  var numgen;
  // first digit
  for (var a = 7; a >= 0; a--) {
    var anum = listofavailable[a];
    listofavailable.splice(a, 1);
    numgen = anum;
    // second digit
    for (var i = 6; i >= 0; i--) {
      var inum = listofavailable[i];
      listofavailable.splice(i, 1);
      numgen = numgen.concat(inum);
      // third digit
      for (var v = 5; v >= 0; v--) {
        var vnum = listofavailable[v];
        listofavailable.splice(v, 1);
        numgen = numgen.concat(vnum);
        // fourth digit
        for (var c = 4; c >= 0; c--) {
          var cnum = listofavailable[c];
          listofavailable.splice(c, 1);
          numgen = numgen.concat(cnum);
          // fifth digit
          for (var g = 3; g >= 0; g--) {
            var gnum = listofavailable[g];
            listofavailable.splice(g, 1);
            numgen = numgen.concat(gnum);
            // sixth digit
            for (var k = 2; k >= 0; k--) {
              var knum = listofavailable[k];
              listofavailable.splice(k, 1);
              numgen = numgen.concat(knum);
              // seventh digit
              for (var b = 1; b >= 0; b--) {
                var bnum = listofavailable[b];
                listofavailable.splice(b, 1);
                numgen = numgen.concat(bnum);

                // eighth digit
                //add whatever else is left in listofavailable[0] to the string
                var jnum = listofavailable[0];
                numgen = numgen.concat(jnum);

                fullarray.push(numgen);
                //console.log(numgen);

                //revert list removals
                listofavailable.push(numgen.substr(numgen.length - 2,1));

                //revert additions to the string
                numgen = numgen.substr(0,numgen.length-2);
              }// b loop
              listofavailable.push(numgen.substr(numgen.length - 1));
              numgen = numgen.substr(0,numgen.length-1);
            }// k loop
            listofavailable.push(numgen.substr(numgen.length - 1));
            numgen = numgen.substr(0,numgen.length-1);
          }// g loop
          listofavailable.push(numgen.substr(numgen.length - 1));
          numgen = numgen.substr(0,numgen.length-1);
        }// c loop
        listofavailable.push(numgen.substr(numgen.length - 1));
        numgen = numgen.substr(0,numgen.length-1);
      }// v loop
      listofavailable.push(numgen.substr(numgen.length - 1));
      numgen = numgen.substr(0,numgen.length-1);
    } // i loop
    listofavailable.push(numgen.substr(numgen));
    numgen = "";
  } // a loop
};
generator();

console.log(fullarray.length);
console.log(fullarray);

To explain what was wrong with the original code.

You are getting an undefined on the second iteration of the b loop

              bnum = listofavailable[b];

this is because your function was emptying out the array of 7 available values, each time it splices out a value, leaving listofavailable as a single element array, listofavailable[0] = "1" . However, when b iterates the second time it is trying to get the element listofavailable[1] which doesn't exist, hence bnum = undefined . When trying to concatenate the undefined value to numgen this then makes numgen = undefined and breaks everything afterwards.

Additionally, the way you're trying to add to an array

fullarray = fullarray + numgen;

doesn't perform how you're intending, you're actually looking for the Array.prototype.push() function, so it would be

fullarray.push(numgen);

and using a reset value for the listofavailable is a good idea, but the way you've implemented it also won't work as

listofavailable = listofavailablereset;

doesn't copy the array elements from listofavailablereset into listofavailable but it just makes listofavailable reference the same array object, hence when you modify one, you're affecting the other. Instead you can just copy your array over using slice() eg.

listofavailable = listofavailablereset.slice();

Note that slice() only creates a shallow copy, object references within each array will both point to the same object.

Check out the Mozilla Javascript Reference pages for excellent javascript reference documentation.

What you're doing by generating these permutations is isomorphic to enumerating all of the 8-digit base 8 numbers, so just do that:

var digits = ['1', '2', '3', '4', '6', '7', '8', '9'];
var n, d, permutations = [], entry;

for (var i = 0, limit = parseInt("100000000", 8); i < limit; ++i) {
  entry = "";
  for (d = 0, n = i; d < digits.length; ++d) {
    entry = digits[n % 8] + entry;
    n = Math.floor(n / 8);
  }
  permutations.push(entry);
}
console.log(permutations);

Note that this will take a long time. Your browser (if you're doing it in a browser) will complain about a busy script.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM