前端小技巧: TS实现数组转树,树转数组

将数组转为树

interface IArrayItem {
  id: number,
  name: string,
  parentId: number
}

interface ITreeNode {
  id: number
  name: string
  children?: ITreeNode[]
}

const arr = [
  {id: 1, name: '部门A', parentId: 0},
  {id: 2, name: '部门B', parentId: 1},
  {id: 3, name: '部门C', parentId: 1},
  {id: 4, name: '部门D', parentId: 2},
  {id: 5, name: '部门E', parentId: 2},
  {id: 6, name: '部门F', parentId: 3}
]

function convert(arr: IArrayItem[]): ITreeItem | null {
  // 用于id和treeNode的映射关系表
  const idToTreeNode: Map<number, ITreeNode> = new Map()
  let root = null
  arr.forEach(item => {
    const {id, name, parentId} = item
    const treeNode: ITreeNode = { id, name }
    idToTreeNode.set(id, treeNode)
    // 找到 parentNode 并加入到它的 children
    const parentNode = idToTreeNode.get(parentId)
    if (parentNode) {
      !parentNode.children && parentNode.children = [] // 没有则初始化一个
      parentNode.children.push(treeNode)
    }
    // 找到根节点
    if (!parentId) root = treeNode
  })
  return root
}

const tree = convert(arr)
console.log('tree: ', tree)
  • 遍历数组,生成 tree node

  • 找到parentNode,加入其children

  • 扩展:

    • 数组:像是mysql, 关系型
    • 树,像是文档型

将树转数组

const obj = {
  id: 1,
  name: '部门a',
  children: [
    {
      id: 2,
      name: '部门b',
      children: [
        { id: 4, name: '部门d'}
        { id: 5, name: '部门e'}
      ]
    },
    {
      id: 3,
      name: '部门c',
      children: [
        { id: 6, name: '部门f'}
      ]
    }
  ]
}

interface IArrayItem {
  id: number,
  name: string,
  parentId: number
}

interface ITreeNode {
  id: number
  name: string
  children?: ITreeNode[]
}

const arr = []

// 使用广度优先遍历,最好

function convert(root: ITreeNode): IArrayItem[] {
  const nodeToParent: Map<ITreeNode, ITreeNode> = new Map()
  const arr: IArrayItem[] = []
  const queue = ITreeNode[] = []
  queue.unshift(root) // 根节点入队

  while(queue.length) {
    const curNode = queue.pop() // 出队
    if (!curNode) break
    const { id, name, children = [] } = curNode

    // 创建数组 item 并 push
    const parentNode = nodeToParent.get(curNode)
    const parentId = parentNode?.id || 0
    const item = { id, name, parentId }
    arr.push(item) // 只在这里加入

    // 子节点入队
    children.forEach(child => {
      // 映射 parent
      nodeToParent.set(child, curNode)
      // 入队
      queue.unshift(child)
    })
  }
}

const arr = convert(obj)
console.log('arr:', arr)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个使用 TypeScript 编写的数组转形结构的方法: ```typescript interface TreeNode { id: number; name: string; children?: TreeNode[]; } function arrayToTree(array: any[], parentId: number): TreeNode[] { const tree: TreeNode[] = []; array.forEach((item: any) => { if (item.parentId === parentId) { const node: TreeNode = { id: item.id, name: item.name }; const children = arrayToTree(array, item.id); if (children.length) { node.children = children; } tree.push(node); } }); return tree; } ``` 该方法接受一个数组和一个父节点 ID,将数组转换为形结构。每个数组元素都应该包含 `id` 和 `name` 属性,并且包含一个 `parentId` 属性,指向该元素的父节点。如果一个元素没有父节点,它的 `parentId` 应该设置为 `null` 或 `undefined`。 该方法返回一个 `TreeNode` 数组,其中每个节点都包含 `id`、`name` 和 `children` 属性。如果一个节点没有子节点,它的 `children` 属性将是 `undefined`。 使用该方法的示例代码: ```typescript const array = [ { id: 1, name: 'A', parentId: null }, { id: 2, name: 'B', parentId: 1 }, { id: 3, name: 'C', parentId: 1 }, { id: 4, name: 'D', parentId: 2 }, { id: 5, name: 'E', parentId: 2 }, { id: 6, name: 'F', parentId: 3 }, { id: 7, name: 'G', parentId: 3 }, ]; const tree = arrayToTree(array, null); console.log(tree); ``` 该示例代码将会输出以下结果: ``` [ { "id": 1, "name": "A", "children": [ { "id": 2, "name": "B", "children": [ { "id": 4, "name": "D" }, { "id": 5, "name": "E" } ] }, { "id": 3, "name": "C", "children": [ { "id": 6, "name": "F" }, { "id": 7, "name": "G" } ] } ] } ] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值