JS從扁平array轉tree

來了老弟發表於2022-06-19
有時我們需要從扁平的陣列結構(flat array),根據id,和pid構建出樹形陣列結構(tree array),這種情形經常出現在巢狀的目錄結構,如下圖:

或者企業的部門架構,也會出現上面的類似結構。
類似上面的情景,假如我們有以下的資料:
let entries = [{
    "id": "12",
    "parentId": "0",
    "text": "Man",
    "level": "1",
    "children": null
  },
  {
    "id": "7",
    "parentId": "12",
    "text": "Other",
    "level": "2",
    "children": null
  },
  {
    "id": "8",
    "parentId": "7",
    "text": "Bird",
    "level": "3",
    "children": null
  },
  {
    "id": "9",
    "parentId": "0",
    "text": "Woman",
    "level": "1",
    "children": null
  },
  {
    "id": "11",
    "parentId": "9",
    "text": "Girl",
    "level": "2",
    "children": null
  }
];

我們期待通過一個演算法,構建出下面的結構:

[
   {
      "id": "12",
      "parentId": "0",
      "text": "Man",
      "level": "1",
      "children": [
         {
            "id": "7",
            "parentId": "12",
            "text": "Other",
            "level": "2",
            "children": [
               {
                  "id": "8",
                  "parentId": "7",
                  "text": "Bird",
                  "level": "3",
                  "children": []
               }
            ]
         }
      ]
   },
   {
      "id": "9",
      "parentId": "0",
      "text": "Woman",
      "level": "1",
      "children": [
         {
            "id": "11",
            "parentId": "9",
            "text": "Girl",
            "level": "2",
            "children": []
         }
      ]
   }
]

也許我們可以想到,在遍歷陣列的時候使用遞迴。沒錯可以解決問題,但是這種方式並不高效。

最近,在Stack Overflow上看到一個方法,感覺不錯,貼出來分享一下:

function list_to_tree(list) {
    var map = {}, node, roots = [], i;
    
    for (i = 0; i < list.length; i += 1) {
      map[list[i].id] = i;      // initialize the map
      list[i].children = [];    // initialize the children
    }
    
    for (i = 0; i < list.length; i += 1) {
      node = list[i];
      if (node.parentId !== "0") {
        // if you have dangling branches check that map[node.parentId] exists
        list[map[node.parentId]].children.push(node);
      } else {
        roots.push(node);
      }
    }
    return roots;
}

演算法的複雜度是Θ(n log(n))。

如果使用遞迴,那麼複雜度是Θ(n^2)。如果資料集比較大,那麼執行的時間會很長。

相關文章