美文网首页
30行代码撸一个性能勉强靠谱的构建树逻辑

30行代码撸一个性能勉强靠谱的构建树逻辑

作者: lane_developer | 来源:发表于2018-01-31 17:13 被阅读0次

大半年前写了一个构建树逻辑,呱呱呱,感觉不够优雅,感觉自己没有对细节做考虑,代码也不够精简,于是自己又动手写了写,整体思想其实差不多,但是针对细节做了一些优化,优化的过程也让我更一步理解了引用类型的数据,也让我发现forEach方法的没注意到的点:就是在用forEach对数组做循环的时候,你删除了数组的一个元素,forEach并没有帮你把循环过程的索引往前移一位,也就是做一个i--的过程,导致整个循环过程会丢失一些元素,所以我使用for循环手动i--。因为这里我是这么想的:一个元素只可能有一个父元素,所以我在对整个的数组做循环的时候,删除已经找到父节点的元素会让整个递归过程更快,整体的思想:就是找到第一级节点,然后递归给第一级节点找子节点,然后递归再给子节点找子子节点,依次递归下去

function hasParentNode(data, item) { // 是否存在父节点
  const index = data.findIndex(c => c.id === item.parentId)
  if (~index) return true
}

function getChildrenNodes(parentNodes, allNodes) { // 获取每一个节点的子节点
  if (parentNodes.length === 0) return
  const node = parentNodes.shift()
  /* allNodes.forEach((item, index) => { // 这里本来是原本的想法,函数式forEach比for循环更优雅
    if (node.id === item.parentId) {
      if (node.children) node.children.push(item)
      else node.children = [item]
      parentNodes.push(item)
      allNodes.splice(index, 1)
    }
  }) */
  for (let i = 0; i < allNodes.length; i += 1) {
    const current = allNodes[i]
    if (node.id === current.parentId) {
      if (node.children) node.children.push(current)
      else node.children = [current]
      parentNodes.push(current)
      allNodes.splice(i, 1) // 删除已经找到父节点的元素
      i -= 1 // 删除元素后把索引往前挪一位
    }
  }
  getChildrenNodes(parentNodes, allNodes)
}

function buildTree(data) {
  const parentNodes = []; // 有子节点的父级节点数组
  data.forEach((item) => {
    if (!hasParentNode(data, item)) parentNodes.push(item)
  })
  if (parentNodes.length <= 0) return
  const dataSource = [...parentNodes] // 最终数组,引用类型的缘故,你操作parentNodes的每一个元素的过程就是操作dataSource的每一个元素的过程,我经常利用这个特性,如果你不想这样,你可能需要深拷贝复制一个新数组,有时候妙用这一特性能给你带来很多的便利
  getChildrenNodes(parentNodes, data)
  return dataSource
}

实际测试

const source = [
  {
    id: 1,
    parentId: undefined,
    groupName: {
      name: '经理1',
      count: 10
    },
  },
  {
    id: 2,
    parentId: null,
    groupName: {
      name: '经理2',
      count: 1
    },
  },
  {
    id: 3,
    parentId: 0,
    groupName: {
      name: '经理3',
      count: 2
    },
  },
  {
    id: 4,
    parentId: 1,
    groupName: {
      name: '主管1',
      count: 4
    },
  },
  {
    id: 5,
    parentId: 1,
    groupName: {
      name: '主管2',
      count: 6
    },
  },
  {
    id: 6,
    parentId: 4,
    groupName: {
      name: '小组1',
      count: 4
    },
  },
  {
    id: 7,
    parentId: 5,
    groupName: {
      name: '小组2',
      count: 4
    },
  },
  {
    id: 8,
    parentId: 2,
    groupName: {
      name: '主管1',
      count: 0
    },
  },
  {
    id: 9,
    parentId: 3,
    groupName: {
      name: '主管1',
      count: 0
    },
  },
];
console.log(buildTree(source))

其实很多原生函数返回的对象都是和原先的对象共享内存地址的,比如find, map等等,你可以了解一下堆栈的概念会帮助你更清楚的理解一些js原生函数的返回值,比如字符串的replace函数肯定是返回了一个新字符而不是在原有字符串上做修改,知识点到为止,自己带着问题去找为什么才是正确学习的方法

let a = [{id: 1, name: 'lane'},{id: 2, name: 'lc'}]
let element = a.find((item) => item.id === 2)
element.name = '数据改变了,引用没有变'
console.log(a)

相关文章

  • 30行代码撸一个性能勉强靠谱的构建树逻辑

    大半年前写了一个构建树逻辑,呱呱呱,感觉不够优雅,感觉自己没有对细节做考虑,代码也不够精简,于是自己又动手写了写,...

  • 大石哲之的《靠谱》读后感

    这本靠谱的书给我最大的感受就是发现自己的不靠谱。书中从逻辑思考和行为技巧两个方面阐述了使一个变得靠谱是有法可依,有...

  • 最新撸糖果APP

    最靠谱的糖果DAPP,百万优质糖果等你拿,下载Prabox,输入邀请码GAFM,撸币撸到手抽筋!注册链接https...

  • 能同时领多种糖果是带刺的么?

    1.最靠谱的糖果DAPP,百万优质糖果等你拿,下载Prabox,输入邀请码ANKP,撸币撸到手抽筋!注册链接htt...

  • 高能:马云钟睒睒是如何发现商机的?

    【沈坤独家观点】由于传统逻辑思维的影响,我们在思考任何问题时,总是在“靠谱”或“不靠谱”的选择中进行,而靠谱或不靠...

  • 代码优化基本原则

    读性优先 如果不是性能瓶颈,就不要因为性能而改写代码 复杂性守恒原理:如果逻辑复杂,代码就应该复杂;如果逻辑简单,...

  • #30天专注橙长#R2-写作-DAY23

    靠谱 当我们称赞一个人靠谱的时候,是对一个人很高的评价。我们也都想成为一个靠谱的人。怎样成为一个靠谱的人呢?靠谱是...

  • 近期思考的一些问题

    看了很多文章,都在讨论逻辑,都推崇逻辑,要遵循逻辑,逻辑要严密。逻辑这个东西真正靠谱吗?是怎么发明的呢? 人在奋斗...

  • Python2.7+selenium3的自动化测试环境搭建

    做好一个小测试,怎么光会性能就够了呢?来,我们好好的把代码撸一撸 我们开始一步一步搭环境:(Windows) ①首...

  • 你见过能挖糖果的Dapp吗?

    最靠谱的糖果DAPP,百万优质糖果等你拿,下载Prabox,输入邀请码V8R3,撸币撸到手抽筋!注册链接https...

网友评论

      本文标题:30行代码撸一个性能勉强靠谱的构建树逻辑

      本文链接:https://www.haomeiwen.com/subject/sadlzxtx.html