繁体   English   中英

递归函数在第一次调用时起作用,但在第二次调用时不起作用

[英]Recursive function that works on first call but not on second

尝试在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
}

您可以使用node-inspector 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. 

它将在数据数组中替换对象条目的“ sons”数组中的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/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM