JavaScript 陣列結構與樹結構的轉換

語言: CN / TW / HK

theme: channing-cyan highlight: an-old-hope


前言

作為前端開發的同學,在與後端進行資料聯調的時候,我們前端的同學處理Array陣列結構的資料是最多的,listtablecard各種需要遍歷的展示顯示我們都會用陣列來處理。當陣列中涉及層級巢狀是我們的陣列結構就需要進行Tree樹結構的轉化,常見的有目錄樹元件,區域選擇元件等等。

這種樹結構資料,前後端都可以處理,當有時候後端就是返回一個數組讓前端處理的時候,我們就可以直接處理就行了。

Array結構 轉 Tree結構

例如: 我們要把下面這種陣列結構的轉化為像tree那樣巢狀的結構

js /** 陣列結構資料 */ const arrayData = [ { id: 2, title: '中國', parent_id: 0 }, { id: 3, title: '廣東省', parent_id: 2 }, { id: 4, title: '廣州市', parent_id: 3 }, { id: 5, title: '天河區', parent_id: 4 }, { id: 6, title: '湖南省', parent_id: 2 }, { id: 1, title: '俄羅斯', parent_id: 0 } ]

使用遞迴的方法

  • 1、遞迴需分為兩個函式來完成
  • 2、 以為返回的遞迴函式主要處理查詢id新增children
  • 3、 由轉化函式將結果返回 ```js /**
  • 遞迴查詢新增children
  • @param {陣列資料} data
  • @param {存放返回結果} result
  • @param {父id} pid */ function getChildren(data, result, pid) { for (const item of data) { if (item.parent_id === pid) { const newItem = { children: [], ...item } result.push(newItem) getChildren(data, newItem.children, item.id) } } }

/* * 轉化方法 * @param {陣列資料} data * @param {父id} pid * @returns / function arrayToTree(data, pid) { let result = [] getChildren(data, result, pid) return result }

console.log(arrayToTree(arrayData, 0)); ```

使用迴圈的方法

  • 1、使用陣列的reduce方法將,data陣列轉為物件儲存在物件變數obj中,每一項的id作為物件的key;
  • 2、遍歷data陣列,判斷parent_id === 0的為第一層陣列物件,pushresult陣列,
  • 3、繼續遍歷,找爹現場,在 2中我們找到陣列的第一層將作為其他層級的父層,
  • 例如: 我們在第一輪的時候 const parent = obj[item.parent_id] 這個parent物件對應的就是parent_id === 0title = 中國或者俄羅斯節點,依此類推在這個parent物件裡不斷新增children屬性,直到他沒有parent_id與自己id一樣的children

js /** * 陣列結構轉為樹結構 * @param {*} data 陣列資料 * @returns */ function arrayToTree(data) { const result = [] const obj = data.reduce((pre, cur) => { pre[cur.id] = cur return pre }, {}) for (let item of data) { if (item.parent_id === 0) { result.push(item) continue } if (item.parent_id in obj) { const parent = obj[item.parent_id]; parent.children = parent.children || []; parent.children.push(item); } } return result } 轉換後的結果圖

image.png

Tree結構 轉 Array結構

例如: 我們要把下面這種tree樹結構的轉化為扁平化的一維陣列 js /** 樹狀形結構資料treeData */ const treeData = [ { id: 2, title: '中國', parent_id: 0, children: [ { id: 3, title: '廣東省', parent_id: 2, children: [ { id: 4, title: '廣州市', parent_id: 3, children: [ { id: 5, title: '天河區', parent_id: 4 } ] } ] }, { id: 6, title: '湖南省', parent_id: 2 } ] }, { id: 1, title: '俄羅斯', parent_id: 0, }, ]

使用遞迴的方法

  • 1、 使用陣列的reduce方法, 解構陣列的每一項,如果有children,就用concat 一層一層的抽取出來,使得每個物件項都包裹在一個[]下 ```js /**
  • 樹結構陣列扁平化
  • @param {*} data 樹結構的陣列
  • @returns */ function treeToArray(data) { return data.reduce((pre, cur) => { const { children = [], ...item } = cur;
    return pre.concat([{ ...item }], treeToArray(children)) }, []); } ```

reduce() 方法對陣列中的每個元素按序執行一個由您提供的 reducer 函式,每一次執行 reducer 會將先前元素的計算結果作為引數傳入,最後將其結果彙總為單個返回值。

concat() 方法用於合併兩個或多個數組。此方法不會更改現有陣列,而是返回一個新陣列。

陣列的相關方法

使用迴圈的方法

image.png

Tree結構根據ID找路徑

使用目錄的時候會有這樣的需求,根據id查詢所在目錄路徑,也是遞迴實現。

  • 1、遍歷樹結構陣列,判斷id 是否為當前項的id,是就返回當前目錄名詞
  • 2、判斷當前項是否有children依此遞迴。

js /** * 根據id查詢所在目錄路徑 * @param {樹結構的陣列資料} tree * @param {要查詢的id} id * @param {初始路徑} path * @returns */ function parseTreePath(tree, id, path = "") { for (let i = 0; i < tree.length; i++) { let tempPath = path; // 避免出現在最前面的/ tempPath = `${tempPath ? tempPath + "/ " : tempPath}${tree[i].title}`; if (tree[i].id == id) return tempPath; else if (tree[i].children) { let reuslt = parseTreePath(tree[i].children, id, tempPath); if (reuslt) return reuslt; } } }; console.log(parseTreePath(treeData, 5));