把平铺的数组转成树

循环

  1. /**
  2. * 把平铺的数组结构转成树形结构
  3. *
  4. * [
  5. * {id:"01", pid:"", "name":"老王" },
  6. * {id:"02", pid:"01", "name":"小张" }
  7. * ]
  8. * 上面的结构说明: 老王是小张的上级
  9. * @param {*} list
  10. * @returns
  11. */
  12. // [
  13. // { 'id': '3129', 'pid': '', 'name': '总裁办' },
  14. // { 'id': '312a', 'pid': '', 'name': '行政部' },
  15. // { 'id': '312b', 'pid': '', 'name': '人事部' },
  16. // { 'id': '312c', 'pid': '', 'name': '财务部' },
  17. // { 'id': '312d', 'pid': '312c', 'name': '财务核算部'},
  18. // { 'id': '312e', 'pid': '312c', 'name': '税务管理部'},
  19. // { 'id': '312f', 'pid': '312c', 'name': '薪资管理部'},
  20. // { 'id': '00d2', 'pid': '', 'name': '技术部'},
  21. // { 'id': '00d3', 'pid': '00d2', 'name': 'Java研发部' },
  22. // { 'id': '00d4', 'pid': '00d2', 'name': 'Python研发部'},
  23. // { 'id': '00d5', 'pid': '00d2', 'name': 'Php研发部'},
  24. // { 'id': '00d6', 'pid': '', 'name': '运营部' },
  25. // { 'id': '00d7', 'pid': '', 'name': '市场部'},
  26. // { 'id': '00d8', 'pid': '00d7', 'name': '北京事业部'},
  27. // { 'id': '00d9', 'pid': '00d7', 'name': '上海事业部'}
  28. // ]
  29. export function tranListToTreeData(list) {
  30. // 最终要产出的树状数据的数组
  31. const treeList = []
  32. // 所有项都使用对象存储起来
  33. const map = {}
  34. // 建立一个映射关系:通过id快速找到对应的元素
  35. list.forEach(item => {
  36. if (!item.children) {
  37. item.children = []
  38. }
  39. map[item.id] = item
  40. })
  41. // map:
  42. // {
  43. // "312c": { 'id': '312c', 'pid': '', 'name': '财务部', children: [{ 'id': '312d', 'pid': '312c', 'name': '财务核算部',children: []}] },
  44. // "312d": { 'id': '312d', 'pid': '312c', 'name': '财务核算部',children: []}
  45. // }
  46. list.forEach(item => {
  47. // 对于每一个元素来说,先找它的上级
  48. // 如果能找到,说明它有上级,则要把它添加到上级的children中去
  49. // 如果找不到,说明它没有上级,直接添加到 treeList
  50. const parent = map[item.pid]
  51. // 如果存在则表示item不是最顶层的数据
  52. if (parent) {
  53. parent.children.push(item)
  54. } else {
  55. // 如果不存在 则是顶层数据
  56. treeList.push(item)
  57. }
  58. })
  59. // 返回出去
  60. return treeList
  61. }

递归

数组转树 - 图1

递归组装树型结构的思路:

  1. 对定的数组和父id, 通过filter找出它的children ```javascript const arr = [ { ‘id’: ‘3129’, ‘pid’: ‘’, ‘name’: ‘总裁办’ }, { ‘id’: ‘312a’, ‘pid’: ‘’, ‘name’: ‘行政部’ }, { ‘id’: ‘312b’, ‘pid’: ‘’, ‘name’: ‘人事部’ }, { ‘id’: ‘312c’, ‘pid’: ‘’, ‘name’: ‘财务部’ }, { ‘id’: ‘312d’, ‘pid’: ‘312c’, ‘name’: ‘财务核算部’ }, { ‘id’: ‘312e’, ‘pid’: ‘312c’, ‘name’: ‘税务管理部’ }, { ‘id’: ‘312f’, ‘pid’: ‘312c’, ‘name’: ‘薪资管理部’ }, { ‘id’: ‘00d2’, ‘pid’: ‘’, ‘name’: ‘技术部’ }, { ‘id’: ‘00d3’, ‘pid’: ‘00d2’, ‘name’: ‘Java研发部’ }, { ‘id’: ‘00d4’, ‘pid’: ‘00d2’, ‘name’: ‘Python研发部’ }, { ‘id’: ‘00d5’, ‘pid’: ‘00d2’, ‘name’: ‘Php研发部’ }, { ‘id’: ‘00d6’, ‘pid’: ‘’, ‘name’: ‘运营部’ }, { ‘id’: ‘00d7’, ‘pid’: ‘’, ‘name’: ‘市场部’ }, { ‘id’: ‘00d8’, ‘pid’: ‘00d7’, ‘name’: ‘北京事业部’ }, { ‘id’: ‘00d9’, ‘pid’: ‘00d7’, ‘name’: ‘上海事业部’ } ]

function f(arr, root = ‘312c’) { const ar = arr.filter(item => item.pid == root) ar.forEach(item => { item.children = f(arr, item.id) }) return ar }

console.dir(f(arr))

  1. 上面的f函数中,每一个轮次的递归都会对整个arr进行循环,进一步对递归的部分做优化:每轮过滤之后,从arr中排除出来被选中的内容,将arr的规模减少。
  2. ```javascript
  3. function f(arr, root = '') {
  4. console.log(arr.length, root)
  5. const ar = []
  6. for(let i = 0; i< arr.length; i++) {
  7. if(arr[i].pid === root) {
  8. ar.push(...arr.splice(i--, 1))
  9. }
  10. }
  11. ar.forEach(item => {
  12. console.log(arr, item)
  13. item.children = f(arr, item.id)
  14. })
  15. return ar
  16. }
  17. console.dir(f(arr))

从树状组件中查找某个元素

  1. var arr = [{
  2. label: '张大大',
  3. children: [
  4. {
  5. label: '小亮',
  6. children: [{ label: '小丽' }, { label: '大光' }]
  7. },
  8. {
  9. label: '小美',
  10. children: [{ label: '小高' }]
  11. },
  12. {
  13. label: '老马',
  14. children: [{ label: '小刘' }, { label: '小华' }, { label: '小李' }]
  15. },
  16. {
  17. label: '老王',
  18. children: [{ label: '小赵' }, { label: '小强', children: [{ label: '小赵1', children: [{ label: '小赵22' }, { label: '小强23' }] }, { label: '小强2' }] }]
  19. },
  20. {
  21. label: '老李',
  22. children: [{ label: '小涛' }]
  23. }
  24. ]
  25. }]
  26. function f(arr, label = '张大大') {
  27. if (arr.length === 0) {
  28. return null
  29. } else {
  30. const rs = arr.find(item => item.label === label)
  31. if (rs) {
  32. return rs
  33. } else {
  34. const r = []
  35. arr.forEach(item => {
  36. if (item.children) {
  37. r.push(...item.children)
  38. }
  39. })
  40. return f(r, label)
  41. }
  42. }
  43. }
  44. console.log(f(arr, '老王'))