我试图制作一个功能,列出所有可能的重复变化。 我做的那个回归"过多的递归"。
function variants(amount, chars, junk){
var junkarray = junk.split(",");
var newjunk;
if(junkarray[junkarray.length-1]==amount){
newjunk = ",";
}
if(junk.length==Math.pow(chars.length, amount)){
console.log(junk);
return;
}else{
for(var i = 0; i < chars.length; i++){
variants(amount, chars, junk+newjunk+chars[i]);
}
}
}
variants(3, ["1", "2"],"");
答案 0 :(得分:3)
您的问题是,您从未点击过退出子句,并且您正在获得无限递归。你的问题在于:
var newjunk;
...
variants(amount, chars, junk+newjunk+chars[i]);
您没有将newjunk
初始化为任何内容,因此当它跳过有可能设置它的部分时,您的变量仍未定义。因此,当您将字符串连接到else子句中的其他变量时,发生的事情是js将值“undefined”转换为“undefined”字符串。对于测试cut-n-paste这一行:
var newjunk; var junk = ""; var chars = ["1","2"]; console.log(result, junk+newjunk+chars[0]);
进入你最喜欢的控制台。请注意,它打印出undefined1
。修复它的方法是将newjunk
初始化为空字符串:
var newjunk = ""
以下是此更改的jsfiddle。
调试递归问题的一个好方法是打破一张纸和笔,并在每行代码中进行物理跟踪,以确保您的exit子句被命中。您还可以以函数内部递增的全局计数变量的形式添加过早退出条件。当此计数变量达到特定值时,退出。
答案 1 :(得分:1)
虽然IngoBürk的答案确实解释了为什么你会遇到无限递归,但它解决了一个稍微不同的问题。这是一个似乎有用的解决方案( Fiddle ):
var variants = function(amount, chars, soFar) {
soFar = soFar || [""];
if (amount === 0) {return soFar;}
var partials = soFar.map(function(partial) {
return chars.map(function(char) {
return partial.concat(char);
});
}).reduce(function(a, b) {return a.concat(b);}, []);
return variants(amount - 1, chars, partials);
};
var v = variants(3, ["1", "2"]);
//=> ["111", "112", "121", "122", "211", "212", "221", "222"]
请注意,这也会导致数据太大的递归问题,但对于相当小的数据集,您应该没问题。
可能有点干净不会宣布第三个参数,它只能在内部用于递归调用,所以 this Fiddle 让它好一点,我想:< / p>
var variants = function(amount, chars) {
var soFar = arguments[2] || [""];
// ... no other changes.
}