昨天遇到一道面试题,手写js将json数组转成tree对象,昨天写错了,今天特意想了下,思路其实挺简单,循环+递归,获取子节点对象。
1 let data = [ 2 {'parent_id': 0, 'id': 1, 'value': 'XXX'}, 3 {'parent_id': 1, 'id': 3, 'value': 'XXX'}, 4 {'parent_id': 4, 'id': 6, 'value': 'XXX'}, 5 {'parent_id': 3, 'id': 5, 'value': 'XXX'}, 6 {'parent_id': 2, 'id': 4, 'value': 'XXX'}, 7 {'parent_id': 1, 'id': 2, 'value': 'XXX'}, 8 ]
主要方法如下,使用的是es6语法
1 let toTree = (arr, key = 'id', pkey = 'pid', children='children') => { 2 if(arr.length === 0){ 3 return {} 4 } 5 return getChildren(arr, 0) // 此处的0代表根节点,如有的根节点标识符为'#',那么此处则为'#' 6 7 // 主要原理是通过查找父节点parent_id为pid的对象,再一层一层往下查找子节点id,看是否存在parent_id等于id的对象 8 function getChildren(arr, pid) { 9 let temp = {} 10 arr.forEach(v => { 11 if(v[pkey] === pid){ 12 temp[v[key]] = {} // 此处可根据相应需求作调整 13 if(Object.keys(getChildren(arr, v[key])).length !== 0){ // 如果存在子节点,此处也可将递归方法抽离出来,以减少代码量和操作 14 temp[v[key]][children] = getChildren(arr, v[key]) // 此处可根据相应需求作调整 15 } 16 } 17 }) 18 return temp 19 } 20 }
测试数据
1 let tree = toTree(data) 2 console.log(JSON.stringify(tree)) 3 4 // 结果为: 5 { 6 "1": { 7 "children": { 8 "2": { 9 "children": { 10 "4": { 11 "children": { 12 "6": {} 13 } 14 } 15 } 16 }, 17 "3": { 18 "children": { 19 "5": {} 20 } 21 } 22 } 23 } 24 }