在函数递归期间维护字符串变量-JavaScript

在函数递归期间维护字符串变量-JavaScript,javascript,string,variables,recursion,scope,Javascript,String,Variables,Recursion,Scope,我创建了一个简单的函数,可以将数字转换为罗马数字。看来除了一件事以外,一切都正常工作 通过代码中的每次递归,保存罗马数字的字符串被重置为“” 通过函数中的递归来维护这样的变量的最佳实践是什么 我尝试在全局范围内声明变量romanStr=“”,并在程序中删除条件声明,当然这是有效的。然而,我知道这是最糟糕的做法 例如,以数字1234为例,它被转换成罗马数字是“MCCXXXIV”。我的程序将只返回“IV”,即最后一次递归的结果 函数转换器(num){ log(`START FUNCTION FRO

我创建了一个简单的函数,可以将数字转换为罗马数字。看来除了一件事以外,一切都正常工作

通过代码中的每次递归,保存罗马数字的字符串被重置为“”

通过函数中的递归来维护这样的变量的最佳实践是什么

我尝试在全局范围内声明变量romanStr=“”,并在程序中删除条件声明,当然这是有效的。然而,我知道这是最糟糕的做法

例如,以数字1234为例,它被转换成罗马数字是“MCCXXXIV”。我的程序将只返回“IV”,即最后一次递归的结果

函数转换器(num){
log(`START FUNCTION FROM START`);
log(`current num:${num}`);
if(typeof romanStr==“未定义”){
var romanStr=“”;
}
常数b数=[1000,500,100,50,10,5,1];
常量符号={
0:[“M”],
2:[“C”、“D”、“M”],
4:[“X”、“L”、“C”],
6:[“I”、“V”、“X”]
};
常数arraySelector=arrNum=>num>=arrNum;
设symbolSetIndex=bNumber.findIndex(数组选择器);
log(`symbolSetIndex:${symbolSetIndex}`);
设symbolSet=romanSymbols[symbolSetIndex];
log(`symbolSet:[${symbolSet}]`);
设numString=num.toString();
设numeric=parseInt(numString[0]);
log(`numeric:${numeric}`);
设nextNum=parseInt(numString.substr(1));
log(`nextNum:${nextNum}`);
//条件语句//
如果(symbolSetIndex==0){

对于(设i=1;i您不需要在所有调用中保留变量。将当前值连接到递归返回的值

函数转换器(num){
log(`START FUNCTION FROM START`);
log(`current num:${num}`);
var romanStr;
常数b数=[1000,500,100,50,10,5,1];
常量符号={
0:[“M”],
2:[“C”、“D”、“M”],
4:[“X”、“L”、“C”],
6:[“I”、“V”、“X”]
};
常数arraySelector=arrNum=>num>=arrNum;
设symbolSetIndex=bNumber.findIndex(数组选择器);
log(`symbolSetIndex:${symbolSetIndex}`);
设symbolSet=romanSymbols[symbolSetIndex];
log(`symbolSet:[${symbolSet}]`);
设numString=num.toString();
设numeric=parseInt(numString[0]);
log(`numeric:${numeric}`);
设nextNum=parseInt(numString.substr(1));
log(`nextNum:${nextNum}`);
//条件语句//
如果(symbolSetIndex==0){

对于(设i=1;i您不需要在所有调用中保留变量。将当前值连接到递归返回的值

函数转换器(num){
log(`START FUNCTION FROM START`);
log(`current num:${num}`);
var romanStr;
常数b数=[1000,500,100,50,10,5,1];
常量符号={
0:[“M”],
2:[“C”、“D”、“M”],
4:[“X”、“L”、“C”],
6:[“I”、“V”、“X”]
};
常数arraySelector=arrNum=>num>=arrNum;
设symbolSetIndex=bNumber.findIndex(数组选择器);
log(`symbolSetIndex:${symbolSetIndex}`);
设symbolSet=romanSymbols[symbolSetIndex];
log(`symbolSet:[${symbolSet}]`);
设numString=num.toString();
设numeric=parseInt(numString[0]);
log(`numeric:${numeric}`);
设nextNum=parseInt(numString.substr(1));
log(`nextNum:${nextNum}`);
//条件语句//
如果(symbolSetIndex==0){

因为(设i=1;i递归是一种函数遗产,因此将其与函数风格结合使用将产生最佳结果。当我第一次看到它以函数风格表达时,罗马数字算法是让我大吃一惊的事情之一:

提供了一个漂亮的编码

toRoman::Integer->String
托罗曼0=“N”
托罗曼x | x>0=snd$foldl f(x,[])convMap
其中f(n,s)(rn,rs)=(l,s++concat(一般复杂的k-rs))
式中(k,l)=divMod n rn
它的简单性真的令人惊讶。我不能相信上面提供的算法的任何部分,但我可以为您将其翻译成JavaScript

我分享这一点是因为它向您展示了一种从完全不同的角度处理问题的方法。CodeReview线程上提供的其他答案提供了更深入的见解。我强烈建议您查看它们:D

constdivmod=(n,d,k)=>
k(n/d>>0,n%d)
常量foldl=(f,init,xs)=>
xs.reduce(f,init)
常量复制=(n,s)=>
s、 重复(n)
常数snd=([[ux])=>
x
const convMap=
[1000,“M”]、[900,“CM”]、[500,“D”]、[400,“CD”]、[100,“C”]
,[90,“XC”],[50,“L”],[40,“XL”],[10,“X”],[9,“IX”],[5,“V”]
,[4,“IV”],[1,“I”]
]
常数toRoman=(x=0)=>
x==0
“N”
:snd(foldl([n,s],[rn,rs])=>
divMod(n,rn,(k,l)=>
[l,s+复制(k,rs)])
,[x,[]
,convMap
)
)
console.log
(托罗曼(0)//N
,托罗曼(7)//VII
,托罗曼(66)//LXVI
,托洛曼(99)//XCIX
,托罗曼(1984)//mcmlxxiv

)
递归是一种函数遗产,因此将其与函数风格结合使用将产生最佳效果。当我第一次看到它以函数风格表达时,罗马数字算法就是其中一个让我大吃一惊的东西:

提供了一个漂亮的编码

toRoman::Integer->String
托罗曼0=“N”
托罗曼x | x>0=snd$foldl f(x,[])convMap
其中f(n,s)(rn,rs)=(l,s++concat(一般复杂的k-rs))
式中(k,l)=divMod n rn
它的简单性真的令人惊讶。我不能相信上面提供的算法的任何部分,但我可以为您将其翻译成JavaScript