function tree(list) {
const result = []
for (let value of list) {
// 排除空字符串的情况
if (!value) {
continue
}
const values = value.split('/')
// 查找树结构的当前级别是否已经存在,不存在则创建对象,并添加入列表。
let current = result.find(item =>item.name === values[0])
if (current === void 0) {
current = {}
result.push(current)
}
for (let i = 0, length = values.lengthi <lengthi++) {
current.name = values[i]
if (i <length - 1) {
// 如果还有下一级内容,判断当前是否有 children,没有则构建.
if (current.children === void 0) {
current.children = []
}
// 查找下一级对象,为下一遍遍历构建对象
let nextCurrent = current.children.find(item =>item.name === values[i + 1])
if (nextCurrent === void 0) {
nextCurrent = {}
current.children.push(nextCurrent)
}
current = nextCurrent
}
}
}
return result
}
============ 假装分割线 ===========
以上代码是生成树的函数,调用 tree 函数并传入你的 input 数据,返回值就是生成的树。百科没找到传代码的地方了。
一、树结构定义一颗树,JS中常见的树形数据结构如下,children属性对应的是子树
let tree = [
{
id: '1',
name: '节点1',
children: [
{
id: '1-1',
name: '节点1-1'
}
]
},
{
id: '2',
name: '节点2',
children: [
{
id: '2-1',
name: '节点2-1'
},
{
id: '2-2',
name: '节点2-2',
children: [
{
id: '2-2-1',
name: '节点2-2-1'
}
]
}
]
},
{
id: '3',
name: '节点3'
}
]
二、深度优先遍历(DFS)
1、递归实现
function treeIterator(tree, func) {
tree.forEach((node) =>{
func(node)
node.children &&treeIterator(node.children, func)
})
}
实现逻辑简述:定义treeIterator函数,传入tree(树)和func(回调函数)两个参数,遍历tree数组,执行回调函数,如果当前节点存在children,则递归调用。
函数调用验证:调用treeIterator函数,传入上文定义好的树结构数组,打印出每个节点的name值。
treeIterator(tree, (node) =>{
console.log(node.name)
})
控制台打印结果如下:
2、循环实现
function treeIterator(tree, func) {
let node, curTree = [...tree]
while ((node = curTree.shift())) {
func(node)
node.children &&curTree.unshift(...node.children)
}
}
实现逻辑简述:
(1)定义node作为当前节点,curTree为传入的树(不影响原数组tree);
(2)执行while循环,curTree数组第一个元素从其中删除,并返回第一个元素赋值给node;
(3)①执行回调函数;②如果当前节点存在子树,则追加到curTree数组的开头,继续执行循环,直到curTree没有元素为止。
函数调用验证:参考上述递归实现验证,方式和结果一致。
三、广度优先遍历(BFS)
function treeIterator(tree, func) {
let node, curTree = [...tree]
while ((node = curTree.shift())) {
func(node)
node.children &&curTree.push(...node.children)
}
}
实现逻辑简述:和上述深度优先遍历的循环实现差不多。区别在于如果当前节点存在子树,则追加到list数组的末尾。
前端数组转为树结构在我们平时开发中经常遇到,主要用到了递归回调。下面的做法可提供一种转换思路。
我们拿到的数据格式是
我们想要用来渲染页面的格式是
第一步,找出最上面的节点。很明显的parentId为空的数据是最上面的节点。
第二步,找出第二节点加到父节点child数组里面
newList 就是我们的结果。
步骤二三也可以这样处理,可以防止curList.length的值不为空的时候无限循环回调