我最近正在學習遞回,因為階乘演算法。然而,我的問題是:
- 如何模擬指定長度的 "for 回圈"?
- 我如何模擬具有指定長度的 "for 回圈"
- 如何用遞回將其索引推入陣列?
- 如何通過遞回將其索引推入一個陣列?
例如,回圈5次,然后把它的 "索引 "推入一個陣列,呈現[1,2,3,4,5]
我創建了2個函式[ 回圈 | 遞回 ],每個函式都試圖實作相同的輸出。回圈 "版本如下:
。function loop(index, length) {
const result = [] 。
for (let i = index; i <= length; i ) result.push(i)。
return result。
}
console. log(loop(1, 5)) 。// [ 1, 2, 3, 4, 5 ]/span>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
然而,"遞回 "版本并沒有列印出想要的結果。
。function recursive(index, length) {
const result = [] 。
result.push(index)。
return (index < length) ? recursive( index, length) : result;
}
console. log(recursive(1, 5)); / [ 5 ]
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
誰能告訴我為什么它沒有輸出 [ 1, 2, 3, 4, 5 ]
uj5u.com熱心網友回復:
因為result在每次函式被呼叫時都被重新初始化為[]。你沒有把之前的result傳給自己,所以它被重置。最后,只有最后一個迭代的索引([5])被送回來。
你可以做的是使用第三個引數,可選的,你可以將其初始化為[]。
function recursive(index,length, result=[]) {
result.push(index)。
return (index < length) ? recursive( index,length, result) : result;
}
console. log(recursive(1,5)) 。// [1,2,3,4,5]
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
uj5u.com熱心網友回復:
Jeremy Thille的答案很好。 它解釋了什么是錯誤的,并給出了一個有用的、可理解的替代方案。 該代碼很干凈,而且由于它是尾部遞回的,如果尾部呼叫優化變得普遍的話,它可以利用尾部呼叫的優勢。 但其中有一個bug:據推測,遞回(10, 3)應該回傳一個空陣列。 這里它將回傳[10]。
雖然我們可以很容易地解決這個問題,但讓我們來看看另一種方法,它在邏輯上更簡單,而且避免了默認引數。 (早先的答案解釋了默認引數的一些潛在問題。請理解,它們仍然是一種有用的、強大的技術,但它們確實有一個缺點。
因此,這里有一個替代版本,都是采用現代語法:
const range=(from, to)=>
from > to ? [] : [from, ... range (from 1, to) ]
還有一種更古老的方式:
function range (from, to) {
if (from > to) {
return [] 。
}
return [from] .concat (range (from 1, to)
}
在這兩個版本中,我們只是通過創建一個新的陣列進行遞回,從from值開始,然后包括所有來自遞回呼叫的值。 當from大于to時,我們遇到了一個基本情況,我們回傳一個空陣列。
這有一個很大的可能的最終缺點。 它不是尾部遞回。 任何遞回呼叫都會立即回傳而無需進一步處理的函式被稱為尾部遞回。 JS 引擎可以對尾部遞回函式進行一些非常有用的優化,以避免遞回堆疊的溢位。
我們可以通過添加默認引數或添加一個將該引數傳遞給內部遞回輔助函式的封裝函式來實作尾部遞回。 這兩種方法都很容易做到。 然而,我們可以看到,這在現代JS中沒有什么區別,因為在回答這個問題時,幾乎沒有引擎支持適當的尾部呼叫,盡管我相信這樣做仍然在規范中。 因此,現在我們不會再去打擾。
下面是這個版本的內容。
下面是這個版本的操作:
。const range = (from, to) =>
from > to ? [] : [from, ... range (from 1, to) ]
console .log(范圍(1, 5)) //=> [1, 2, 3, 4, 5]/span>
console .log (范圍(4, 4)。//=> [4]
console .log(范圍(5, 1))。//=> []
.as-console-wrapper {max-height: 100% ! important; top: 0}
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
uj5u.com熱心網友回復:
一種變通方法是在你的遞回函式中添加一個累加器,以便將你在第一次呼叫開始時開始的陣列的每一步都帶入。
。function recursive(index, length) {
const result = [] 。
result.push(index)。
return recursiveAcc( index, length, result)。
}
function recursiveAcc(index, length, result) {
result.push(index)。
return (index < length) ? recursiveAcc( index, length, result) : result;
}
console. log(recursive(1, 5))。) // [ 1, 2, 3, 4, 5 ]/span>
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" class="snippet-box-edit snippet-box-result" frameborder="0"></iframe>
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/319317.html
標籤:
上一篇:按級別扁平化一個動態的層次結構樹
