这个递归函数如何创建范围工作?

时间:2011-06-13 10:47:06

标签: javascript arrays recursion

this SO-question中的选定答案中,这个非常巧妙的函数会创建一个范围从1到i的数组:

function range1(i){return i?range1(i-1).concat(i):[]}

它完美无缺。叫我傻,但我无法理解 它是如何运作的。假设我们有range1(5)。现在进入函数,我们有i,因此它返回参数i-1(4)并将i(5)连接到它。但在这里我被困住了:range1 如何知道它与数组有什么关系?我会说在第一次运行后返回值(只要我们有i,所以i!==0)就是一个数字。并且Number没有concat方法。有人可以解释一下吗?我错过了什么?

7 个答案:

答案 0 :(得分:11)

我已经扩展了这段代码,因为我发现这种方式更容易理解。

function range1(i){
  if (i != 0) {
     return range1(i - 1).concat(i);
  } else {
     return [];
}

此功能背后的逻辑是,如果您需要3元素列表(range(3)),则可以获取2元素列表(range1(i - 1))并添加3到它的末尾.concat(i)。除此之外,您只需处理range1(0)为空数组[]的特殊情况,您就完成了。

想象一下对range1(2)的调用。自i != 0以来,我们得到了

range(2) = range(1).concat(2)

range(1)返回range(0).concat(1),告诉我们

range(2) = range(0).concat(1).concat(2)

嗯,range(0)是什么?从i == 0开始,我们得到了我们需要的空数组([])!

range(2) = [].concat(1).concat(2) -> [1, 2]

答案 1 :(得分:9)

  

现在进入这个功能,我们有,   所以它用参数返回自己   i-1(4)和concats i(5)。

不,它不会自行返回。它的作用是调用自身,即递归,然后它返回该调用的结果,最后一个元素连接起来。

因此,range1(5)会调用range1(4),它会调用range1(3),依此类推。当它达到零时,它将停止调用并返回一个空数组。

range1(0)会返回[],因此range1(1)会返回[].concat(1) [1],然后range1(2)会返回[1].concat(2) [1,2] {1}},等等。当我们返回range1(5)时 它会返回[1,2,3,4].concat(5) [1,2,3,4,5]

注意:此函数适用于创建小型数组,但如果需要大型数组,则创建数组并使用常规循环填充它会快得多。

答案 2 :(得分:2)

递归的基本情况是[],因此递归的尾部将返回一个数组,其他步骤将连接到[](以及之前的步骤)。

答案 3 :(得分:2)

我们取范围1(4):

range1(4) => range1(3).concat(4)
range1(3) => range1(2).concat(3)
range1(2) => range1(1).concat(2)
range1(1) => range1(0).concat(1)
range1(0) => []

现在取第一行并将range1(3)替换为下一行的等效值。你明白了:

range1(4) => range1(2).concat(3).concat(4)

继续替换range1引用,直到没有任何剩余。最终结果:

range1(4) => [].concat(1).concat(2).concat(3).concat(4)

答案 4 :(得分:0)

range1函数始终返回一个数组。

它是一个空数组(对于i == 0)或连接数组。

答案 5 :(得分:0)

在基本情况下range1返回一个定义concat的空数组。然后,当它展开时,范围中的数字被添加到数组中。

答案 6 :(得分:0)

直到我变成0除了使用带有rediced值的caling函数之外没什么好处,但是当它用0调用时它返回[] - 一个空数组,在前一个调用中使用了concat方法......它看起来像range(0)。 concat(1)=> [] .concat(1)所以[1]返回上一个调用:[1] .concat(2)等等开始