簡體   English   中英

將遞歸函數轉換為JavaScript中的迭代

[英]Convert a recursive function to an iteration in javascript

我無法將遞歸函數轉換為迭代。 考慮以下功能

function getTreeDataFromRows (id, rows) {
  let ret_val = []

  for (let i = 0; i < rows.length; i++) {
    let row = rows[i]

    if (id == row.id_parent) {
      let new_element = {
        id:         row.id,
        id_parent:  row.id_parent,
        value:      row.value,
        data:       getTreeDataFromRows(row.id, rows)
      }

      for (let property in row) {
        if ('id' == property || 'id_parent' == property || 'value' == property) {
          continue
        }
        new_element[property] = row[property]
      }

      ret_val.push(new_element)
    }
  }

  return ret_val
}

我有一個類似於以下內容的json作為輸入

[{
    "id": "c-1",
    "id_parent": null,
    "value": "Chapter 1"
  },
  {
    "id": "a-1",
    "id_parent": "c-1",
    "value": "Article 1.1"
  },
  {
    "id": "a-2",
    "id_parent": "c-1",
    "value": "Article 1.2"
  },
  {
    "id": "c-2",
    "id_parent": null,
    "value": "Chapter 2"
  },
  {
    "id": "a-21",
    "id_parent": "c-2",
    "value": "Article 2.1"
  },
  {
    "id": "a-22",
    "id_parent": "c-2",
    "value": "Article 2.2"
  },
  {
    "id": "a-221",
    "id_parent": "a-22",
    "value": "Quote 221 from article 2.2"
  },
  {
    "id": "a-222",
    "id_parent": "a-22",
    "value": "Quote 222 from article 2.2"
  }
]

輸出必須是這樣的:

[{
    "id": "c-1",
    "id_parent": null,
    "value": "Chapter 1",
    "data": [{
        "id": "a-1",
        "id_parent": "c-1",
        "value": "Articole 1.1",
        "data": []
      },
      {
        "id": "a-2",
        "id_parent": "c-1",
        "value": "Articole 1.2",
        "data": []
      }
    ]
  },
  {
    "id": "c-2",
    "id_parent": null,
    "value": "Chapter 2",
    "data": [{
        "id": "a-21",
        "id_parent": "c-2",
        "value": "Articole 2.1",
        "data": []
      },
      {
        "id": "a-22",
        "id_parent": "c-2",
        "value": "Articole 2.2",
        "data": [{
            "id": "a-221",
            "id_parent": "a-22",
            "value": "Quote 221 from article 2.2",
            "data": []
          },
          {
            "id": "a-222",
            "id_parent": "a-22",
            "value": "Quote 222 from article 2.2",
            "data": []
          },
        ]
      },
    ]
  }
]

樹表需要此輸出。 當處理大量數據時,遞歸函數會給出“超出最大調用堆棧大小”錯誤。 樹也可以有很多子代(兒子,孫子等)。 我嘗試使用堆棧數組編寫一個for循環,但未成功。 我很困惑,我的代碼也可能造成混亂。

function functionWithIteration (rows) {
  var my_stack = [null]
  var final_val = []

  while( my_stack.length > 0 ) {
    var ret_val = []
    var first_time = true
    var id = my_stack.pop()
    var temp_val = []
    for (let i = 0; i < rows.length; i++) {

      var row = rows[i]
      var signal = true
      if (id == row.id_parent) {
        signal = false
        var new_element = {
          id: row.id,
          id_parent: row.id_parent,
          value: row.value,
          data: []
        }

        for (let property in row) {
          if (property == 'id' || property == 'id_parent' || property == 'value') {
            continue
          }
          new_element[property] = row[property]
        }

        if (first_time){
          ret_val.push(new_element)
          first_time = false
        }
        else {
          ret_val[ret_val.length - 1].data.push(new_element)
        }
      }
      if ( signal) {
        temp_val.push(ret_val)
        my_stack.push(row.id)
      }
    }
    final_val.push(temp_val)
  }

  return final_val
}

任何幫助將不勝感激! 謝謝!

您可以對已知ID和父對象使用對象的單循環方法。

此解決方案不希望數據按排序順序。

 var data = [{ id: "c-1", id_parent: null, value: "Chapter 1" }, { id: "a-1", id_parent: "c-1", value: "Article 1.1" }, { id: "a-2", id_parent: "c-1", value: "Article 1.2" }, { id: "c-2", id_parent: null, value: "Chapter 2" }, { id: "a-21", id_parent: "c-2", value: "Article 2.1" }, { id: "a-22", id_parent: "c-2", value: "Article 2.2" }, { id: "a-221", id_parent: "a-22", value: "Quote 221 from article 2.2" }, { id: "a-222", id_parent: "a-22", value: "Quote 222 from article 2.2" }], tree = function (data, root) { var o = {}; data.forEach(function (a) { if (o[a.id] && o[a.id].children) { a.children = o[a.id].children; } o[a.id] = a; o[a.id_parent] = o[a.id_parent] || {}; o[a.id_parent].children = o[a.id_parent].children || []; o[a.id_parent].children.push(a); }); return o[root].children; }(data, null); console.log(tree); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

一旦弄清楚保存對對象的引用的簡單步驟,這是一個相當簡單的解決方案。 遍歷數組並創建一個以元素id為鍵的對象。 然后,您要使用該元素來引用元素以添加其子元素。

 var data = [{ "id": "c-1", "id_parent": null, "value": "Chapter 1" }, { "id": "a-1", "id_parent": "c-1", "value": "Article 1.1" }, { "id": "a-2", "id_parent": "c-1", "value": "Article 1.2" }, { "id": "c-2", "id_parent": null, "value": "Chapter 2" }, { "id": "a-21", "id_parent": "c-2", "value": "Article 2.1" }, { "id": "a-22", "id_parent": "c-2", "value": "Article 2.2" }, { "id": "a-221", "id_parent": "a-22", "value": "Quote 221 from article 2.2" }, { "id": "a-222", "id_parent": "a-22", "value": "Quote 222 from article 2.2" } ] // we use reduce to loop over the object to build up our new object. var result = data.reduce((obj, itm) => { // store it into a obj so we can reference it obj.temp[itm.id] = itm // check to see if we have a parent if (itm.id_parent) { // if we have a parent see if data is set yet // if not, set it to an empty array obj.temp[itm.id_parent].data = obj.temp[itm.id_parent].data || [] // push the child into the parent obj.temp[itm.id_parent].data.push(obj.temp[itm.id]) } else { // If we have no parent, than it is a root element // or we push it into an array to keep track of it obj.order.push(obj.temp[itm.id]) } // return the object for reduces next iteration return obj }, { temp:{}, order:[]}) // init recude with an empty object and array .order // return the order console.log(result) 

該解決方案期望父母出現在他們的孩子之前。 如果不是這種情況,那么您可以做幾件事。 無論哪種方式,您都會創建一個“臨時”對象,直到找到真正的對象為止。

我認為您的邏輯有誤。 當它遞歸時,它似乎從頭開始。 直觀地講,這將使遞歸實例陷入與之前完全相同的條件,從而無限遞歸 (就邏輯而言,循環變量i多個嵌套實例具有相同的值。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM