JS使用reduce()方法處理樹形結構資料
阿新 • • 發佈:2021-05-13
定義
reduce() 方法對陣列中的每個元素執行一個由您提供的reducer函式(升序執行),將其結果彙總為單個返回值。
reduce() 與forEach()、map()、filter()這些方法一樣,也會對陣列中的每一項進行遍歷,但是reduce() 可以將遍歷的前一個數組項產生的結果與當前遍歷項進行運算。
語法
array.reduce(function(prev,cur,index,array){ ... },init);
回撥函式中的引數:
- prev 必需。表示呼叫回撥時的返回值,或者初始值 init。
- cur 必需。表示當前元素。
- index 可選。表示當前元素的索引。
- array 表示原陣列。
- init 可選。初始值,作為第一次呼叫回撥函式的第一個引數。
其中常用引數:prev 和 cur
注意:回撥函式第一次執行時,prev和cur的取值有兩種情況:如果呼叫reduce()時提供了初始值init,prev取init值,cur取陣列中的第一個值,此時索引從0開始;如果沒有提供初始值init,則prev取陣列中的第一個值,cur取陣列中的第二個值,此時索引從1開始。
例項
1. 沒有傳遞初始值init
const arr = [1,3,5,7]
arr.reduce(functiowww.cppcns.comn(prev,arr){
console.log(prev,index)
return prev + cur
})
每次呼叫的引數和返回值如下表:
www.cppcns.comcallback | prev | cur | index | array | return value |
---|---|---|---|---|---|
第1次 | 1 | 3 | 1 | [1,7] | 4 |
第2次 | 4 | 5 | 2 | [1,7] | 9 | http://www.cppcns.com
第3次 | 9 | 7 | 3 | [1,7] | 16 |
因為沒有傳入初始值,所以索引是從1開始,callback被呼叫三次,開始時prev的值為陣列第一項1,cur的值為3,相加之後返回值4作為下一輪迴調的prev值,然後繼續下一輪的回撥,直至完成後返回。
2. 傳遞初始值的情況下
const arr = [1,7] arr.reduce(function(prev,index) return prev + cur },10)
每次呼叫的引數和返回值如下表:
callback | prev | cur | index | array | return value |
---|---|---|---|---|---|
第1次 | 10 | 1 | diWJJk0 | [1,7] | 11 |
第2次 | 11 | 3 | 1 | [1,7] | 14 |
第3次 | 14 | 5 | 2 | [1,7] | 19 |
第4次 | 19 | 7 | 3 | [1,7] | 26 |
3. 陣列去重
const arr = ['ab','v','d','ab','h','e','dc','f'] const newArr = arr.reduce(functiondiWJJk(prev,cur){ !prev.includes(cur) && prev.push(cur) return prev },[]) console.log(newArr) // ["ab","v","d","h","e","dc","f"]
執行的步驟如下:
- 初始化一個空陣列
- 第一次呼叫時,prev 為初始值即空陣列,cur 為陣列中的第一項 arr[1],然後在 prev 中查詢 cur 是否已經存在,如果不存在就將該項新增到 prev 中,並 prev 返回進入下一次回撥
- 第二次回撥時,prev 為第一次的返回值,cur 為陣列中的第二項 arr[2],然後在 prev 中查詢 cur 是否已經存在,如果不存在就將該項新增到 prev 中,並 prev 返回進入下一次回撥
- 最後將 prev 這個陣列返回
4. 利用 reduce 對陣列中的 Object 物件進行分組及合併
//從後臺獲取的物件陣列,根據物件的type進行分組合併成tree樹形展示資料 const dataArr = [ { type: '治理層',name: 'hive_82',reserve: '2',id: 1 },{ type: '原始資料層',name: 'qwe',reserve: '1',id: 2 },{ type: '貼源層',name: 'mysql_exchangis',reserve: '3',id: 3 },{ type: '治理層',name: 'links_188',id: 4 },name: 'mysql_ces',id: 5 } ] const treeData = dataArr.reduce((cur,next) => { const obj = cur.find(curItem => curItem.label === next.type) if (obj) { if (obj.children.indexOf(next.id) === -1) { //去重處理 obj.children.push({ ...next,label: next.name }) } } else { const newObj = { label: next.type,children: [{ ...next,label: next.name }] } cur.push(newObj) } return cur },[]) // 合併後的結果: treeData = [ { label: '治理層',children: [ { type: '治理層',id: 1,label: 'hive_82' },id: 4,label: 'links_188' } ] },{ label: '原始資料層',children: [ { type: '原始資料層',id: 2,label: 'qwe' } ] },{ label: '貼源層',children: [ { type: '貼源層',name: 'mysql_exchangis',id: 3,label: 'mysql_exchangis' },id: 5,label: 'mysql_ces' } ] } ]
5. 利用 reduce 處理選單後端返回的選單結構
需要根據 parentId 將這些資料轉換成層級結構。
方法一:
const dataArr = [ {id: '18',name: '重置密碼',parentId: '30',parentName: '使用者管理'},{id: '13',name: '審計日誌',parentId: '29',parentName: '系統管理'},{id: '29',name: '系統管理',parentId: '0',parentName: null},{id: '14',name: '修改',parentId: '33',parentName: '部門管理'},{id: '2',name: '使用者列表',{id: '30',name: '使用者管理',{id: '33',name: '部門管理',{id: '37',name: '新增使用者',{id: '6',name: '新增',{id: '7',name: '刪除',parentName: '部門管理'} ] //建立選單id的對映關係 const idMapping = dataArr.reduce((prev,next,i) => { prev[next.id] = i return prev },{}) const treeData = [] dataArr.map(el => { // 一級選單 if (el.parentId === '0') { treeData.push(el) return } // 通過對映找到父元素 const parentEl = dataArr[idMapping[el.parentId]] // 把當前元素新增到父元素的`children`陣列中 parentEl.children = [...(parentEl.children || []),el] }) console.log(treeData)
方法二:
//根據parentId建立對映關係 const result = dataArr.reduce((prev,next) => { prev[next.parentId] ? prev[next.parentId].push(next) : prev[next.parentId] = [next]; return prev; },{}); Object.keys(result).map(key => { result[key].map((item,i) => { result[item.id] ? item.children = result[item.id] : '' }); }) this.treeData = result[0] console.log(treeData)
還可以通過遞迴的方法來實現,具體就不贅述了
最後生成的資料結構如下圖所示:
以上就是js使用reduce()方法處理樹形結構資料的詳細內容,更多關於JS的資料請關注我們其它相關文章!