当 Javascript 中使用了很多 for 循环时,输出未定义
When many for loops are used in Javascript, output is undefined
如 https://jsfiddle.net/LBMF_1/gacLzLnn/ 所示,我的代码表面上生成了 8 位数字的所有可能排列,在 for 循环中使用 for 循环。(问题结尾 ) 我的代码在语法上似乎是正确的,因为 JSHint 和 in-chrome 控制台都没有错误。这是我的错误,还是这是JS引起的通病? 可能是前者,因为看起来应该可行
奖励积分:
还有哪些其他方法可以用来避免嵌套的 for 循环?
你不知道我是多么感谢任何帮助。
另外,Stack Overflow 和新段落是怎么回事?
代码在这里,在我看来,当 运行 应该在控制台中粘贴一个非常长的数字列表时,却出现了很多 "undefined"。
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;
}
}
}
}
}
}
}
};
这是根据您的 fiddle 修改后的实现。
请注意,您的示例中缺少数字“0”和“5”,我不确定这是否有意。
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);
解释一下原来的代码有什么问题。
你在 b 循环的第二次迭代中得到了一个未定义的
bnum = listofavailable[b];
这是因为你的函数清空了 7 个可用值的数组,每次它拼接出一个值,留下 listofavailable
作为单个元素数组,listofavailable[0] = "1"
。但是,当 b 第二次迭代时,它试图获取不存在的元素 listofavailable[1]
,因此 bnum = undefined
。当尝试将 undefined
值连接到 numgen
时,这会生成 numgen = undefined
并随后破坏所有内容。
此外,您尝试添加到数组的方式
fullarray = fullarray + numgen;
没有按照您的预期执行,您实际上是在寻找 Array.prototype.push() 函数,所以它会是
fullarray.push(numgen);
为 listofavailable 使用重置值是个好主意,但您实现它的方式也不会像
listofavailable = listofavailablereset;
不会将数组元素从 listofavailablereset
复制到 listofavailable
但它只是使 listofavailable
引用相同的数组对象,因此当你修改一个时,你会影响其他。
相反,您可以使用 slice()
例如
复制数组
listofavailable = listofavailablereset.slice();
注意 slice()
只创建一个浅拷贝,每个数组中的对象引用都指向同一个对象。
查看 Mozilla Javascript Reference 页面以获得优秀的 javascript 参考文档。
你通过生成这些排列所做的事情与枚举所有 8 位基数 8 的数字同构,所以就这样做:
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);
请注意,这将需要 长 的时间。您的浏览器(如果您在浏览器中执行此操作)会抱怨脚本繁忙。
如 https://jsfiddle.net/LBMF_1/gacLzLnn/ 所示,我的代码表面上生成了 8 位数字的所有可能排列,在 for 循环中使用 for 循环。(问题结尾 ) 我的代码在语法上似乎是正确的,因为 JSHint 和 in-chrome 控制台都没有错误。这是我的错误,还是这是JS引起的通病? 可能是前者,因为看起来应该可行 奖励积分: 还有哪些其他方法可以用来避免嵌套的 for 循环? 你不知道我是多么感谢任何帮助。 另外,Stack Overflow 和新段落是怎么回事? 代码在这里,在我看来,当 运行 应该在控制台中粘贴一个非常长的数字列表时,却出现了很多 "undefined"。
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;
}
}
}
}
}
}
}
};
这是根据您的 fiddle 修改后的实现。 请注意,您的示例中缺少数字“0”和“5”,我不确定这是否有意。
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);
解释一下原来的代码有什么问题。
你在 b 循环的第二次迭代中得到了一个未定义的
bnum = listofavailable[b];
这是因为你的函数清空了 7 个可用值的数组,每次它拼接出一个值,留下 listofavailable
作为单个元素数组,listofavailable[0] = "1"
。但是,当 b 第二次迭代时,它试图获取不存在的元素 listofavailable[1]
,因此 bnum = undefined
。当尝试将 undefined
值连接到 numgen
时,这会生成 numgen = undefined
并随后破坏所有内容。
此外,您尝试添加到数组的方式
fullarray = fullarray + numgen;
没有按照您的预期执行,您实际上是在寻找 Array.prototype.push() 函数,所以它会是
fullarray.push(numgen);
为 listofavailable 使用重置值是个好主意,但您实现它的方式也不会像
listofavailable = listofavailablereset;
不会将数组元素从 listofavailablereset
复制到 listofavailable
但它只是使 listofavailable
引用相同的数组对象,因此当你修改一个时,你会影响其他。
相反,您可以使用 slice()
例如
listofavailable = listofavailablereset.slice();
注意 slice()
只创建一个浅拷贝,每个数组中的对象引用都指向同一个对象。
查看 Mozilla Javascript Reference 页面以获得优秀的 javascript 参考文档。
你通过生成这些排列所做的事情与枚举所有 8 位基数 8 的数字同构,所以就这样做:
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);
请注意,这将需要 长 的时间。您的浏览器(如果您在浏览器中执行此操作)会抱怨脚本繁忙。