2017-03-25 53 views
0

試圖在node.js中創建遞歸函數,第一次調用有效,但第二次失敗。遞歸函數適用於第一次調用,但不適用於第二次調用

爲了更容易地向我們展示失敗的地方,我做了一個例子,我用一個對象數組替換了數據庫,並在函數findElements內搜索。

let data = [ 
    {id: 1, value: "1st", articleId: 1, lvl: 0, sons: [3, 7], positif: 3, negatif: 2}, 
    {id: 2, value: "2nd", articleId: 2, lvl: 0, sons: [], positif: 5, negatif: 8}, 
    {id: 3, value: "3rd", articleId: 1, lvl: 1, sons: [5, 6, 8], positif: 9, negatif: 4}, 
    {id: 4, value: "4th", articleId: 1, lvl: 0, sons: [], positif: 3, negatif: 52}, 
    {id: 5, value: "5th", articleId: 1, lvl: 2, sons: [], positif: 8, negatif: 2}, 
    {id: 6, value: "6th", articleId: 1, lvl: 2, sons: [9], positif: 3, negatif: 1}, 
    {id: 7, value: "7th", articleId: 1, lvl: 1, sons: [], positif: 5, negatif: 0}, 
    {id: 8, value: "8th", articleId: 1, lvl: 2, sons: [], positif: 3, negatif: 0}, 
    {id: 9, value: "9th", articleId: 1, lvl: 3, sons: [], positif: 123, negatif: 102} 
] 

function findElements(object, elementName, value) { 
    let res = [] 
    object.forEach((element) => { 
    if(element[elementName] == value){ 
     res.push(element) 
    } 
    }) 
    return res 
} 

function recursiveFindSons(element) { 
    for (let i = 0; i < element.length; i++) { 
    for (let j = 0; j < element[i].sons.length; j++) { 
     console.log(element[i].sons[j]) 
     element[i].sons[j] = findElements(data, 'id', element[i].sons[j])[0] 
     if(element[i].sons[j].sons.length>0) 
     { 
     element[i].sons[j] = recursiveFindSons([element[i].sons[j]]) 
     } 
    } 
    } 
    return element 
} 

app.get('/', function(req, res) { 
    let result = recursiveFindSons(findElements(data, 'lvl', 0)) 
    let json = JSON.stringify({result}, null, 2) 
    res.status(200).send(json) 
}) 

console.log(element[i].sons[j])顯示問題:第一個呼叫 日誌:

3 
5 
6 
9 
8 
7 

日誌中的第二個電話:

[ { id: 3, 
value: '3rd', 
articleId: 1, 
lvl: 1, 
sons: [ [Object], [Object], [Object] ], 
positif: 9, 
negatif: 4 } ] 

我明白的東西保持第一的結果在記憶中打電話,但我不知道如何避免這種情況,我不明白爲什麼......任何人都可以幫忙解釋我嗎?

編輯與SciFiThief解決方案

function recursiveFindSons(elements, result) { 

    function copyElement(element) { 
    return {id: element.id, value: element.value, articleId: element.articleId, lvl: element.lvl, sons: [], positif: element.positif, negatif: element.negatif} 
    } 

    if(!result) { 
    result = [] 
    for(var i=0; i<elements.length; i++) { 
     result.push(copyElement(elements[i])) 
    } 
    } 

    for (let i = 0; i < elements.length; i++) { 
    for (let j = 0; j < elements[i].sons.length; j++) { 
     let elById = findElements(data, 'id', elements[i].sons[j])[0] 
     result[i].sons.push(copyElement(elById)) 
     console.log(result) 
     if(elById.sons.length>0) 
     { 
     result[i].sons[j] = recursiveFindSons([elById], result[i].sons[j][0])[0] 
     } 
    } 
    } 
    return result 
} 

回答

0

你可以使用節點檢查https://www.npmjs.com/package/node-inspector調試應用程序,打算徹底你的函數的每一行。你會很快發現它有什麼問題。

function recursiveFindSons(element) { 
    for (let i = 0; i < element.length; i++) { 
    for (let j = 0; j < element[i].sons.length; j++) { 
     // 1. The next line is mutating the data you go through 
     element[i].sons[j] = findElements(data, 'id', element[i].sons[j])[0] 
     if(element[i].sons[j].sons.length > 0) { 
     element[i].sons[j] = recursiveFindSons([element[i].sons[j]]); 
     } 
    } 
    } 
    return element; 
} 

首先,對數據進行變異以找到您感興趣的內容是一件壞事。

element[i].sons[j] = ... // this is mutating of source data. 
         // You should not do this, 
         // it makes function's behavior unpredictable. 
         // It's like iterating through array and deleting 
         // elements from it on each iteration. 

它將在一個條目的「兒子」數組中替換ID的數組,直到數據數組中。 同樣放在這裏:

element[i].sons[j] = recursiveFindSons([element[i].sons[j]]); 

我想你想你所提供的第一日誌的輸出。要做到這一點,你可以做這樣的事情:

function recursiveFindSons(elements, result) { 
    result = result || []; // define result array on first call or use it from args. 
         // There's no original data mutations, only local result variable 

    for (let i = 0; i < elements.length; i++) { 
    for (let j = 0; j < elements[i].sons.length; j++) { 
     let son = elements[i].sons[j]; 
     result.push(son); 
     let elById = findElements(data, 'id', son)[0]; 
     if(elById.sons.length > 0) { 
     recursiveFindSons([elById], result); // pass result array to the next function call 
     } 
    } 
    } 
    return result; 
} 

的jsfiddle:https://jsfiddle.net/fwbumpx9/

+0

謝謝!我不想要我提供的第一個日誌,但要添加相應的兒子數字中的第一個日誌的ID。對不好的解釋抱歉。 我已成功解決您的問題: **編輯原始文章中的代碼** 它讓我安排推送到更好的形式,我認爲這將是很好的。 – fleau

相關問題