在javascript中将循环函数转换为递归函数

在javascript中将循环函数转换为递归函数,javascript,function,loops,recursion,tail-recursion,Javascript,Function,Loops,Recursion,Tail Recursion,我试图自学如何编写递归函数,有人建议尝试将循环转换为递归。因此,我尝试将第一个for循环函数更改为递归函数。这是我的密码: // Function that uses for loop. function onlyOne(value1, value2, value3) { var array = [value1, value2, value3]; var count = 0; for(var i = 0; i < array.length; i++) {

我试图自学如何编写递归函数,有人建议尝试将循环转换为递归。因此,我尝试将第一个for循环函数更改为递归函数。这是我的密码:

// Function that uses for loop.
function onlyOne(value1, value2, value3) {
    var array = [value1, value2, value3];
    var count = 0;
    for(var i = 0; i < array.length; i++) {
        if(!!array[i] === true) {
            count ++;
        }
    } if(count === 1) {
        return true;
    } else {
        return false;
    }
}

// Function that uses recursion.
function onlyOne2(a, b, c) {
    var array = [a, b, c];
    var count = 0;
    var numTrue = 0;
    if(!!array[count] === true) {
        numTrue++;
    }
    if(count === array.length-1) {
        if(numTrue === 1) {
            return true;
        } else {
            return false;
        }
    }else {
        count++;
        return onlyOne2(a, b, c);
    }
}

console.log(onlyOne2(true, false, false));
//用于循环的函数。
仅限一个函数(值1、值2、值3){
变量数组=[value1,value2,value3];
var计数=0;
对于(var i=0;i

每个函数的目的都是在只有一个参数为真时返回真。否则,函数返回false。for循环函数工作正常。然而,当我使用递归函数时,我得到了一个错误:超过了最大调用堆栈大小。我想知道我做错了什么。谢谢你的帮助

上述代码的问题是,每当函数递归时,再次声明
count
numTrue
并因此发生无限循环,以下是正确的代码(声明
count
numTrue
为全局:

var计数=0;
var numTrue=0;
功能仅限2(a、b、c){
var数组=[a,b,c];
如果(!!数组[计数]==真){
numTrue++;
}
if(count==array.length-1){
如果(numTrue==1){
返回true;
}否则{
返回false;
}
}否则{
计数++;
仅返回2(a、b、c);
}
}
log(仅限2(真、假、假));
您的方法存在一些问题
  • if(!!数组[i]==true)
    直接使用布尔值:
    if(数组[i])
您要求返回一个
true
true

if (count === 1) { // <- Use this comparison to return the specific value.
    return true;
    ^
} else {
    return false;
    ^
}
您必须使用索引
i

看看这个带有这些修复的代码片段
//用于循环的函数。
仅限一个函数(值1、值2、值3){
变量数组=[value1,value2,value3];
var计数=0;
对于(var i=0;iconsole.log(onlyOne2(true,false,false,0,0));
这很有趣。好的,如果数组中正好有一个项是truthy,那么我们有一个函数返回true。让我们考虑递归中的基本要求

基本情况下,数组为空:

if (!array.length)
  return false;
基本情况下,数组中只有一个元素:

if (array.length == 1)
  return !!array[0] === true
否则:

let next = f(rest-of-array)

if (!!array[0] === true)
  return !next
else
  return next
JavaScript代码:

函数f(arr,i){
//与!array.length相同
如果(i==arr.length)
返回false;
//与array.length==1相同
如果(i==arr.length-1)
返回!!arr[i]
//与f相同(数组的其余部分)
设next=f(arr,i+1)
如果(!!arr[i])
回来!下一个
下一个返回
}
输出:

f([undefined,2,0],0)
=>正确
f([1,2,未定义],0)
=>错误
f([undefined,false,1],0)
=>正确
f([5,false,false],0)
=>正确

您可以为想要的值和递归函数使用计数器

它可以处理任意数量的参数

function onlyOne(a,b,c){
 let arr = Array.from(arguments);
 let count = 0;
 let item = arr.shift();
 if(true === item){
    ++count;
 }
 if(arr.length > 0) {
    count += onlyOne.apply(this,arr);
    return count == 1;
 }
 return count;
}
仅功能(计数、v、…剩余){
如果(v){//检查值
如果(!count){//检查计数为零
return false;//因为发现比需要的更真实
}
计数--;//递减计数
}
如果(!rest.length){//请检查长度是否为零
return!count;//return not count
}
仅返回(count,…rest);//带有count和rest的尾部调用
}
log(仅(1,false,false,false));//false
log(仅(1,false,false,true));//true
log(仅(1,false,true,false));//true
log(仅(1,false,true,true));//false
log(仅(1,真,假,假));//真
log(仅(1,真,假,真));//假
console.log(仅(1,真,真,假));//假
log(仅(1,true,true,true));//false
console.log('----');
log(仅(2,false,false,false));//false
log(仅(2,false,false,true));//false
log(仅(2,false,true,false));//false
log(仅(2,false,true,true));//true
log(仅(2,真,假,假));//假
log(仅(2,true,false,true));//true
log(仅(2,true,true,false));//true
console.log(仅(2,true,true,true));//false

。作为控制台包装{max height:100%!important;top:0;}
您可以将任何
for
循环转换为递归:

let a=0, b=1,
for (let n=5; n > 0; n--) {
  const tmpa = a;
  a = b; 
  b += tmpa;
}
function onlyOne(arr) {
  function iterate (index, count) {
    if (index < len && count <= 1) {
      return iterate(
        index + 1, 
        count + (array[index] ? 1 : 0)
      );
    }
    return count;
  }
  const len = array.length; // cache
  const count = iterate(0, 0);
  return count === 1;
}
此处
a
b
n
发生变化,原因是
a
值具有第6个斐波那契数。因此,我们将其设为参数并返回:

function forLoop(n, a, b) {
  if(n > 0) {
    return forLoop(n - 1, b, a + b);
  }
  return a;
}
const a = forLoop(5, 0, 1);
因此,对于使用
for
循环的函数:

function onlyOne(value1, value2, value3) {
  const array = [value1, value2, value3];
  let count = 0;
  for(var i = 0; i < array.length; i++) {
    if(!!array[i] === true) {
      count ++;
    }
  } 
  if(count === 1) {
    return true;
  }
  return false;
}
由于您只有3个元素,这可能已经足够好了,但是假设您想要为一个数组实现类似的功能,您应该计划以已知的速度返回。在
for
版本中,它将如下所示:

function onlyOne(arr) {
  let count = 0;
  const len = array.length; // cache
  for (index = 0; index < len; index++) {
    if (arr[index]) {
      count++; 
      if(count > 1) return false; // early return
    }
  }
  return count === 1;
}
仅限一个函数(arr){
让计数=0;
const len=array.length;//缓存
为了
function onlyOne(arr) {
  function iterate (index, count) {
    if (index < len && count <= 1) {
      return iterate(
        index + 1, 
        count + (array[index] ? 1 : 0)
      );
    }
    return count;
  }
  const len = array.length; // cache
  const count = iterate(0, 0);
  return count === 1;
}
function onlyOne(a,b,c){
 let arr = Array.from(arguments);
 let count = 0;
 let item = arr.shift();
 if(true === item){
    ++count;
 }
 if(arr.length > 0) {
    count += onlyOne.apply(this,arr);
    return count == 1;
 }
 return count;
}