Javascript递归函数不返回值?

IT技术 javascript recursion
2021-02-13 13:03:07

我正在解决一个 codewars 问题,我很确定我已经让它工作了:

function digital_root(n) {
    // ...
    n = n.toString();
    if (n.length === 1) {
        return parseInt(n);
    } else {
        let count = 0;
        for (let i = 0; i < n.length; i++) {
            //console.log(parseInt(n[i]))
            count += parseInt(n[i]);
        }
        //console.log(count);
        digital_root(count);
    }
}

console.log(digital_root(942));

本质上它应该找到一个“数字根”:

数字根是一个数字中所有数字的递归和。给定n,取n的数字之和。如果该值有两位数,则继续以这种方式减少,直到产生一位数。这仅适用于自然数。

所以我实际上在最后得到了正确的答案,但无论出于何种原因,if语句(我正在观察调试器运行并且它确实输入了该语句,它会说返回值是正确的值。

但是然后它跳出if语句并尝试从主digital_root函数返回

为什么是这样?当它击中if声明时,它不应该打破这一点吗?我很困惑为什么它试图跳出if语句,然后尝试从中不返回任何内容,digital_root因此返回值最终未定义?

3个回答

你没有返回里面的任何东西else它应该是:

return digital_root(count);
^^^^^^^

为什么?

digital_root应该返回一些东西。如果我们用一位数来调用它,那么该if部分就会被执行,并且由于我们从那里返回if,所以一切正常。但是如果我们提供一个由多个数字组成的数字,那么 else 部分就会被执行。现在,在else我们计算的digital_root部分中,count但我们不使用该值(应该返回的值)。上面的行可以分成两行代码,以便于理解:

var result = digital_root(count); // get the digital root of count (may or may not call digital_root while calculating it, it's not owr concern)
return result;                    // return the result of that so it can be used from the caller of digital_root
@msmith1114 检查解释!我希望它有用。
2021-03-22 13:03:07
废话,我不太习惯使用递归。我想....你能解释一下我们为什么要退货吗?我猜是不是因为你将“未来”的value归还给“现在”本身?
2021-04-05 13:03:07

代码审查

我的评论是下面的代码评论

// javascript generally uses camelCase for function names
// so this should be digitalRoot, not digital_root
function digital_root(n) {
    // variable reassignment is generally frowned upon
    // it's somewhat silly to convert a number to a string if you're just going to parse it again
    n = n.toString();
    if (n.length === 1) {
        // you should always specify a radix when using parseInt
        return parseInt(n);
    } else {
        let count = 0;
        for (let i = 0; i < n.length; i++) {
            //console.log(parseInt(n[i]))
            count += parseInt(n[i]);
        }
        // why are you looping above but then using recursion here?
        // missing return keyword below
        digital_root(count);
    }
}

console.log(digital_root(942));

简单的递归解决方案

考虑到其中一些事情,让我们简化我们的方法digitalRoot......

const digitalRoot = n =>
  n < 10 ? n : digitalRoot(n % 10 + digitalRoot((n - n % 10) / 10))
  
console.log(digitalRoot(123))         //          => 6
console.log(digitalRoot(1234))        //       10 => 1
console.log(digitalRoot(12345))       //       15 => 6
console.log(digitalRoot(123456))      //       21 => 3
console.log(digitalRoot(99999999999)) // 99 => 18 => 9


使用减少

数字根是一个数字中所有数字的递归和。给定n,取n的数字之和。如果该值有两位数,则继续以这种方式减少,直到产生一位数。这仅适用于自然数。

如果您打算使用实际的归约函数,我将在这里向您展示如何做到这一点。首先,我们将创建一个toDigits函数,它接受一个整数,并返回一个由其数字组成的数组。然后,我们将digitalRoot通过使用add用空和初始化reducer来减少这些数字来实现0

// toDigits :: Int -> [Int]
const toDigits = n =>
  n === 0 ? [] :  [...toDigits((n - n % 10) / 10), n % 10]

// add :: (Number, Number) -> Number
const add = (x,y) => x + y

// digitalRoot :: Int -> Int
const digitalRoot = n =>
  n < 10 ? n : digitalRoot(toDigits(n).reduce(add, 0))
      
console.log(digitalRoot(123))         //          => 6
console.log(digitalRoot(1234))        //       10 => 1
console.log(digitalRoot(12345))       //       15 => 6
console.log(digitalRoot(123456))      //       21 => 3
console.log(digitalRoot(99999999999)) // 99 => 18 => 9

它是一个递归函数,代码应该有点像这样

function digital_root(n) {
    // ...
    n=n.toString();
    if(n.length === 1){
         return parseInt(n);
    }
    else
    {
    let count = 0;
    for(let i = 0; i<n.length;i++)
    {
    //console.log(parseInt(n[i]))
    count+=parseInt(n[i]);
    }
   //console.log(count);
   return digital_root(count);
   }
}

您应该返回相同的函数,而不是仅仅调用它来获取正确的调用堆栈

那么问题是为什么它返回 undefined 而不是一个值,我只是更正了代码的递归部分
2021-03-16 13:03:07
对于您的下一个问题,请参阅此链接了解什么是数字根 thonky.com/nine-hours-nine-persons-nine-doors/digital-root digital_root (123123123) = 9 而不是 18 如果我正确理解了数字根概念.如果我错了,我很抱歉,请分享您对数字根源的看法
2021-03-17 13:03:07
你是对的。我把数字根误认为是数字的简单总和。谢谢
2021-03-19 13:03:07
为什么要使用循环和递归?在这种情况下,它几乎是一个或另一个 - 无论如何这都是无关紧要的;你的函数返回9digital_root(123123123),但应该返回18
2021-04-05 13:03:07