JavaScript:递归计数基本案例
Posted
技术标签:
【中文标题】JavaScript:递归计数基本案例【英文标题】:JavaScript: Recursive Countup Base Case 【发布时间】:2022-01-19 22:11:09 【问题描述】:我目前正在做一个 javascript 练习,要求我创建一个递归函数,该函数从开始数到结束数(包括)进行计数。我已经找到了解决方案,但我一直在尝试使我认为是同义的基本案例起作用,但我无法理解它。
function rangeOfNumbers(startNum, endNum)
if (endNum < startNum)
return [];
const arr = rangeOfNumbers(startNum, endNum - 1);
arr.push(endNum);
return arr;
;
console.log(rangeOfNumbers(1, 5)) = [1, 2, 3, 4, 5]
上面的代码有效,但下面的代码无效:
function rangeOfNumbers(startNum, endNum)
if (endNum = startNum)
return [endNum];
const arr = rangeOfNumbers(startNum, endNum - 1);
arr.push(endNum);
return arr;
;
console.log(rangeOfNumbers(1, 5)) = [1]
后者仅输出带有startNum
的数组。我很困惑为什么它不计算递归的其他堆栈,有人可以向我解释一下吗?
【问题讨论】:
【参考方案1】:递归是一种函数式遗产,因此将其与函数式风格一起使用会产生最佳效果。这意味着要避免诸如突变、变量重新分配和其他副作用之类的事情 -
function rangeOfNumbers (startNum, endNum)
if (startNum > endNum)
return []
else
return [startNum].concat(rangeOfNumbers(startNum + 1, endNum))
console.log(JSON.stringify(rangeOfNumbers(0, 3)))
console.log(JSON.stringify(rangeOfNumbers(3, 7)))
console.log(JSON.stringify(rangeOfNumbers(9, 3)))
[0,1,2,3]
[3,4,5,6,7]
[]
使用函数样式意味着您可以将函数调用替换为 return
值,并且总是得到正确的结果。这使您能够对程序进行推理,就好像它们是公式或equations。如果您使用具有命令式风格的递归,那根本不可能 -
rangeOfNumbers(3,6)
== [3].concat(rangeOfNumbers(4,6))
== [3].concat([4].concat(rangeOfNumbers(5,6)))
== [3].concat([4].concat([5].concat(rangeOfNumbers(6,6))))
== [3].concat([4].concat([5].concat([6].concat(rangeOfNumbers(7,6)))))
== [3].concat([4].concat([5].concat([6].concat([]))))
== [3].concat([4].concat([5].concat([6])))
== [3].concat([4].concat([5,6]))
== [3].concat([4,5,6])
== [3,4,5,6]
你可以写出和纯函数表达式一样的东西——
const range = (start, end) =>
start > end
? []
: [start, ...range(start + 1, end)]
console.log(JSON.stringify(range(0, 3)))
console.log(JSON.stringify(range(3, 7)))
console.log(JSON.stringify(range(9, 3)))
[0,1,2,3]
[3,4,5,6,7]
[]
这个可以可视化为-
range(3,6)
== [3, ...range(4, 6)]
== [3, ...[4, ...range(5, 6)]]
== [3, ...[4, ...[5, ...range(6, 6)]]]
== [3, ...[4, ...[5, ...[6, ...range(7, 6)]]]]
== [3, ...[4, ...[5, ...[6, ...[]]]]]
== [3, ...[4, ...[5, ...[6]]]]
== [3, ...[4, ...[5, 6]]]
== [3, ...[4, 5, 6]]
== [3, 4, 5, 6]
只需再增加一个条件,我们也可以支持反向范围 -
const range = (start, end) =>
start > end
? range(end, start).reverse()
: start == end
? [start]
: [start, ...range(start + 1, end)]
console.log(JSON.stringify(range(0, 3)))
console.log(JSON.stringify(range(3, 7)))
console.log(JSON.stringify(range(9, 3)))
[0,1,2,3]
[3,4,5,6,7]
[9,8,7,6,5,4,3] // <- inverse
最后一个可以可视化为 -
range(9,6)
== range(6,9).reverse()
== [6, ...range(7,9)].reverse()
== [6, ...[7, ...range(8,9)]].reverse()
== [6, ...[7, ...[8, ...range(9,9)]]].reverse()
== [6, ...[7, ...[8, ...[9]]]].reverse()
== [6, ...[7, ...[8, 9]]].reverse()
== [6, ...[7, 8, 9]].reverse()
== [6, 7, 8, 9].reverse()
== [9, 8, 7, 6]
【讨论】:
【参考方案2】:第二个代码块不起作用的原因是if (endNum = startNum)
行。通过使用单个等号,您将startNum
分配给endNum
。
要检查是否相等,您可以使用 equality operator (==
) 或 strict equality operator (===
):
if (endNum === startNum)
return [endNum]
【讨论】:
是的,我刚刚意识到 :'(((。谢谢!【参考方案3】:问题是您使用的是赋值运算符而不是相等运算符。
正确
if (endNum === startNum)
不正确
if (endNum = startNum)
【讨论】:
我太笨了........非常感谢! 我们都这样做。大声笑。以上是关于JavaScript:递归计数基本案例的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript-函数(调用参数returnarguments匿名回调递归函数)函数案例