首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在JS中以递归方式计算上、下计数

在JS中以递归方式计算上、下计数
EN

Stack Overflow用户
提问于 2021-01-28 09:42:23
回答 3查看 777关注 0票数 1

我目前正在研究函数式编程技术。有关于这个问题的主题,,特别是关于java ,但没有关于JS。

我想要创建一个递归函数,它可以首先计数直到我决定的极限,从我表示的数字开始,然后在达到极限时开始计数。我已经可以用for循环来完成这个任务了,但是感觉就像硬编码的,因为我提供了循环中的数字.

基本上是这样的:

代码语言:javascript
复制
counter(0,10);
// 0, 1, 2, 3 ... 10, 9, 8... 0

以下是我的想法:

代码语言:javascript
复制
counter = (number, limit) => {
limit !=== 0

if ( number = limit ) {
  counter(number -1, limit -1)
  console.log(number)
} else if ( number < limit ) {
  counter(number + 1, limit + 1)
  }
}

这背后的想法是,如果数字低于上限计数向上,,如果它们相等,将每个参数减少1,以继续满足第一个if条件

当我在v8上运行这个命令时,它给出了一个rangeError“达到的最大堆栈大小”.

而且,这不应该是一个无限循环。

循环版本:

代码语言:javascript
复制
for (let i = 0; i < 11; i++ ) { console.log(i) }
for (let i = 9; i < 11 && i > -1; i--) { console.log(i) }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-01-28 09:57:08

您不需要循环返回或减少值,就像当您到达大小写(停止递归的东西)时,您将跳回包含前一个value的调用函数。

代码语言:javascript
复制
counter(0, 10) // logs: 0
    |           ^
    |           | (returns back to)
    |---> counter(1, 10) // logs: 1
              |             ^
              |             | (returns back to)
              |---> counter(2, 10) // logs: 2 <---
                        |                         | (returns back to)
                        |                         |
                        ........   ---> counter(10, 10) // logs: 10 - base case

counter()的每个调用都会再次调用计数器(在上面的图中显示了子counter调用),然后这些调用将打印它们当前的value。到达基大小写时,打印当前值并返回,这将使您将控制传递回调用函数。我的意思是,当您调用一个函数时,该函数将运行。函数完成后,代码从函数最初调用的位置返回:

代码语言:javascript
复制
function bar() {
  console.log("bar");
}

console.log("foo"):
bar(); // call the function makes the code execution jump up into `bar` function. When that completes, our code execution jumps back to the next line, which logs "baz"
console.log("baz");

在我们的counter()示例中,调用子counter()函数的位置是其父counter函数,当子函数完成执行(返回)时,我们跳过(传递控制)到其子函数。一旦控制权被传回。对于调用函数(即上面图表中的父函数),您可以再次记录value,因为它包含以前的value值。

代码语言:javascript
复制
function counter(value, limit) {
  if(value === limit) {
    console.log(value);
  } else {
    console.log(value); // on the way down / going deeper (increment)
    counter(value+1, limit);
    console.log(value); // on the way up / coming up from the depths (decrement)
  }
}

counter(0,10);
// 0, 1, 2, 3 ... 10, 9, 8... 0

票数 3
EN

Stack Overflow用户

发布于 2021-01-28 16:56:21

递归是一种功能继承,因此将它与函数样式一起使用会产生最好的结果。这意味着避免诸如突变,可变的重新分配,以及其他副作用。

如果开始,

  1. a,大于stop,b,我们已经达到了基本情况。返回空结果时,[]
  2. (inductive) a小于或等于b。如果[a]
  3. (inductive) a等于b,则返回单例结果,即山的“峰值”,则b a小于b。在子问题的a

上重新查找a + 1, b并附加/预置结果。

这是一个纯函数表达式,下面的注释与上面的编号解释相匹配-

代码语言:javascript
复制
const uppendown = (a, b) =>
  a > b
    ? []                                // #1
: a == b
    ? [ a ]                             // #2
: [ a, ...uppendown(a + 1, b), a ]      // #3
    
const ex1 =
  uppendown(0, 10)
  
const ex2 =
  uppendown(3,7)

const ex3 =
  uppendown(9,7)
  
console.log(JSON.stringify(ex1))
// [0,1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1,0]

console.log(JSON.stringify(ex2))
// [3,4,5,6,7,6,5,4,3]

console.log(JSON.stringify(ex3))
// []

代码语言:javascript
复制
uppenDown(3,7)
= [ 3, ...uppendDown(3 + 1, 7), 3 ]                   // #3
= [ 3, 4, ...uppendDown(4 + 1, 7), 4, 3 ]             // #3
= [ 3, 4, 5, ...uppendDown(5 + 1, 7), 5, 4, 3 ]       // #3
= [ 3, 4, 5, 6, ...uppendDown(6 + 1, 7), 6, 5, 4, 3 ] // #2
= [ 3, 4, 5, 6, 7, 6, 5, 4, 3 ]
代码语言:javascript
复制
uppendown(9,7)                        // #1
= []

如果出于某些任意的原因,您不喜欢链接函数样式三元表达式,则可以将它们转换为命令式样式if语句-

代码语言:javascript
复制
function uppendown (a, b)
{ if (a > b)
    return []                                // #1
  else if (a == b)
    return [ a ]                             // #2
  else
    return [ a, ...uppendown(a + 1, b), a ]  // #3
}
    
const ex1 =
  uppendown(0, 10)
  
const ex2 =
  uppendown(3,7)

const ex3 =
  uppendown(9,7)
  
console.log(JSON.stringify(ex1))
// [0,1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1,0]

console.log(JSON.stringify(ex2))
// [3,4,5,6,7,6,5,4,3]

console.log(JSON.stringify(ex3))
// []

如果希望逐个显示数字而不是返回数组,则可以使用JavaScript的生成器。注意每个程序变体之间惊人的相似-

代码语言:javascript
复制
function* uppendown (a, b)
{ if (a > b)
    return                                  // #1
  else if (a == b)
    yield a                                 // #2
  else
    ( yield a                               // #3
    , yield *uppendown(a + 1, b)            //
    , yield a                               //
    )
}
    
for (const x of uppendown(3, 7))
  console.log(x)
  
// 3
// 4
// 5
// 6
// 7
// 6
// 5
// 4
// 3

票数 3
EN

Stack Overflow用户

发布于 2021-01-28 11:15:02

像这样吗?

代码语言:javascript
复制
console.clear();
{
  "use strict"
  
  // Curry function
  const nextStepInit = start => max => {
    let increment = 1;
    let counter = start;
    
    return () => {
      counter += increment;
      if (counter >= max) {
        increment = -increment;
        return max;
      }
      if (counter <= start) {
        return start;
      }
      return counter;
    }
  }
  
  // this is a function, because nextStep(start)(max) returns a function
  const nextStep = nextStepInit(0)(10)
  
  const output = result => document.getElementById('output').value = result
  
  const onClick = () => output(nextStep())
  
  output(0)
  
  document.getElementById('next-step').addEventListener('click', onClick)
}
代码语言:javascript
复制
<button id="next-step">Next Step</button><br>
<input id="output" disabled/>

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65934524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档