js树形结构操作

Array 转 树状结构

实现思路

  1. 按照pid分组,分组可以大大减少递归次数。。(Array分组的最好方式是用对象接收Array的项,该对象的key值就是分组凭证)
  2. 按照pid和id的匹配 递归 已分组的数据。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* Array转树形结构的算法
* @params list 代转化数组
* @params parentId 起始节点(默认为'0')
* @params pKey 父节点key值。默认pid
* @params cKey 当前节点唯一标志。默认id
*/
export function getTrees(list, parentId = '0', pKey = 'pid', cKey = 'id') {
let items = {}
// 获取每个节点的直属子节点,*记住是直属,不是所有子节点
for (let i = 0; i < list.length; i++) {
let key = list[i][pKey]
if (items[key]) {
items[key].push(list[i])
} else {
items[key] = []
items[key].push(list[i])
}
}
return formatTree(items, parentId, cKey)
}

// 利用递归格式化每个节点
function formatTree(items, parentId, cKey) {
let result = []
if (!items[parentId]) {
return result
}
for (let t of items[parentId]) {
const temp = formatTree(items, t[cKey], cKey)
if (temp.length > 0) {
t.children = temp
}
result.push(t)
}
return result
}

根据节点值查找树形结构中的路径、子树

实现思路

  1. 使用深度优先算法,递归按照层级查找,默认找
  2. 找到指定节点,开始返回路径,

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* 根据节点值查找树形结构中的路径
* @param {String|Number} value 节点的值
* @param {Array} tree 树形结构
* @param {String} attr 匹配值的属性
* @param {String} childAttr 匹配子节点数组的属性
*/
export function findTreePath(value, tree, attr = 'id', childAttr = 'children') {
if (!(tree instanceof Array)) {
console.error('tree: 请传入树形数组进行过滤!')
return []
}
if (tree.length === 0) return

for (let i = 0; i < tree.length; i++) {
const item = tree[i]

if (item[attr] === value) {
// 如果找到, 则跳出
return [item[attr]]
}
if (item[childAttr]) {
const path = findTreePath(value, item[childAttr], attr, childAttr)
if (path.length > 0) {
// 子节点找到, 把本节点插入到第一个
path.splice(0, 0, item[attr])
return path
}
}
}
return []
}

/**
* 查找树的指定节点
* @param {String|Number} value 节点的值
* @param {Array} tree 树形结构
* @param {String} attr 匹配值的属性
* @param {String} childAttr 匹配子节点数组的属性
*/
export function findTreeNode(value, tree, attr = 'id', childAttr = 'children') {
if (!(tree instanceof Array)) {
console.error('tree: 请传入树形数组进行过滤!')
return null
}
if (tree.length === 0) return

for (let i = 0; i < tree.length; i++) {
const item = tree[i]

if (item[attr] === value) {
// 如果找到, 则跳出
return item
}
if (item[childAttr]) {
const node = findTreeNode(value, item[childAttr], attr, childAttr)
if (node) {
// 找到即返回
return node
}
}
}

return null
}
坚持原创技术分享,您的支持将鼓励我继续创作!