Javascript递归函数没有返回值?

3

我正在解决一个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个回答

10

你在else语句内没有返回任何内容。正确的写法应该是:

您需要在else语句中加入返回内容。

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

为什么?

digital_root 应该返回一些东西。如果我们使用一位数调用它,那么 if 部分将被执行,由于我们从那个 if 返回,所以一切正常。但是如果我们提供的数字超过一位,则执行 else 部分。现在,在 else 部分中,我们计算 countdigital_root,但我们没有使用该值(应该返回的值)。上面的代码行可以分成两行代码,这样更容易理解:

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
@msmith1114 请查看解释!希望对你有用。 - ibrahim mahrir

2

代码审查

我的评论在下面的代码注释中。

// 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


使用reduce函数

数字根是指一个数的所有数字递归相加的结果。给定一个数字n,将其各个位上的数字相加。如果得到的值有两位数字,就继续这样减少,直到得到一位数字为止。这只适用于自然数。

如果你想使用实际的reduce函数,我将在这里向你展示如何做到。首先,我们将创建一个名为toDigits的函数,该函数接受一个整数并返回其数字数组。然后,我们将使用初始化为空和为0的add reducer来减少这些数字,从而实现digitalRoot函数。

// 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


0

这是一个递归函数,代码应该类似于这样

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);
   }
}

你应该返回同一个函数而不是仅仅调用它以获取正确的调用堆栈。


你为什么要同时使用循环和递归?在这种情况下,基本上只能选其一。不过这并不是重点;无论如何,你的函数对于 digital_root(123123123) 返回了 9,但应该返回 18 - Mulan
问题是为什么它返回未定义而不是一个值,我只是纠正了代码的递归部分。 - subramanian
请参阅以下链接了解数字根是什么:http://www.thonky.com/nine-hours-nine-persons-nine-doors/digital-root如果我正确理解数字根的概念,digital_root(123123123)= 9,而不是18。如果我错了,请告诉我您对数字根的看法。 - subramanian
你是正确的。我把数字根误认为是简单的数字总和了。谢谢。 - Mulan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接