前端小技巧: 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)