JavaScript 陣列結構與樹結構的轉換
theme: channing-cyan highlight: an-old-hope
前言
作為前端開發的同學,在與後端進行資料聯調的時候,我們前端的同學處理Array
陣列結構的資料是最多的,list
、table
、card
各種需要遍歷的展示顯示我們都會用陣列來處理。當陣列中涉及層級巢狀是我們的陣列結構就需要進行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
的為第一層陣列物件,push
到result
陣列, - 3、繼續遍歷,找爹現場,在
2
中我們找到陣列的第一層將作為其他層級的父層, - 例如: 我們在第一輪的時候
const parent = obj[item.parent_id]
這個parent
物件對應的就是parent_id === 0
的title = 中國或者俄羅斯
節點,依此類推在這個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
}
轉換後的結果圖
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() 方法用於合併兩個或多個數組。此方法不會更改現有陣列,而是返回一個新陣列。
使用迴圈的方法
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));