树形数据操作
let arr = [
{
id: '1',
title: '节点1',
children: [
{
id: '1-1',
title: '节点1-1'
},
{
id: '1-2',
title: '节点1-2'
}
]
},
{
id: '2',
title: '节点2',
children: [
{
id: '2-1',
title: '节点2-1'
}
]
}
]
/**
广度优先遍历
**/
function breadthFisrstSearch(tree, cb) {
let node = null
let list = [...tree]
while (node = list.shift()) {
cb(node)
node.children && list.push(...node.children)
}
}
breadthFisrstSearch(arr, (data) => {
data.text = data.id.toString() + data.title
console.log(data)
})
/**
========================
深度优先遍历
========================
**/
/**
先序遍历
**/
function depthFirstTraversal(tree, cb) {
tree.forEach(item => {
cb(item)
item.children && depthFirstTraversal(item.children, cb)
})
}
/**
后序遍历
**/
function depthFirstTraversalEnd(tree, cb) {
tree.forEach(item => {
item.children && depthFirstTraversalEnd(item.children, cb)
cb(item)
})
}
/**
先序遍历 循环版
**/
function depthFirstTraversalWithLoop(tree, cb) {
let node = null
let list = [...tree]
while (node = list.shift()) {
cb(node)
node.children && list.unshift(...node.children)
}
}
/**
后序遍历 循环版
**/
function depthFirstTraversalEndWithLoop(tree, cb) {
let node = null
let list = [...tree]
let i = 0
while (node = list[i]) {
let len = node.children ? node.children.length : 0
if (!len || list[i - 1] === node.children[len - 1]) {
cb(node)
i++
} else {
list.splice(i, 0, ...node.children)
}
}
}
/**
数据过滤
**/
function treeFilter(tree, func) {
// 使用map复制一下节点,避免修改到原树
return tree.map(node => ({ ...node })).filter(node => {
node.children = node.children && treeFilter(node.children, func)
return func(node) || (node.children && node.children.length)
})
}
/**
数据查找
**/
function treeFind(tree, cb) {
for (const data of tree) {
if (cb(data)) return data
if (data.children) {
const res = treeFind(data.children, cb)
if (res) return res
}
}
return null
}
/**
节点路径
**/
function treeFindPath(tree, cb, path = []) {
if (!tree) return []
for (const data of tree) {
path.push(data.id)
if (cb(data)) return path
if (data.children) {
const findChildren = treeFindPath(data.children, cb, path)
if (findChildren.length) return findChildren
}
path.pop()
}
return []
}
树形数据与数组转换
let list = [
{
id: '1',
title: '节点1',
parentId: '',
},
{
id: '1-1',
title: '节点1-1',
parentId: '1'
},
{
id: '1-2',
title: '节点1-2',
parentId: '1'
},
{
id: '2',
title: '节点2',
parentId: ''
},
{
id: '2-1',
title: '节点2-1',
parentId: '2'
}
]
function ArrayToTree(arr) {
let tree = []
let map = {}
arr.forEach(item => {
item.children = []
map[item.id] = item
})
arr.forEach(item => {
let parent = map[item.parentId]
if (parent) {
parent.children.push(item)
} else {
tree.push(item)
}
})
return tree
}
function arrayToTreeWithReduce(arr) {
let map = arr.reduce((map, item) => {
item.children = []
map[item.id] = item
return map
}, {})
return arr.filter(item => {
map[item.parentId] && map[item.parentId].children.push(item)
return !item.parentId
})
}
//递归实现
function treeToList(tree, result = [], level = 0) {
tree.forEach(node => {
result.push(node)
node.level = level + 1
node.children && treeToList(node.children, result, level + 1)
})
return result
}
// 循环实现
function treeToList(tree) {
let node, result = tree.map(node => (node.level = 1, node))
for (let i = 0; i < result.length; i++) {
if (!result[i].children) continue
let list = result[i].children.map(node => (node.level = result[i].level + 1, node))
result.splice(i + 1, 0, ...list)
}
return result
}