JS 树形结构与数组结构相互转换

树形结构数据如下

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
const tree = [
{
id: "1",
children: [
{
id: "2",
children: [
{
id: "3",
children: [{ id: "4" }]
},
{ id: "5" },
{
id: "6",
children: [{ id: "7" }]
}
]
},
{
id: "8",
children: [{ id: "9" }]
}
]
},
{
id: "a",
children: [{ id: "b" }]
}
];

将树形结构转换为有父子关系属性的数组结构

思路一:初始化一个空数组,从 tree 的顶端开始遍历,当前节点有子节点时,一边继续遍历子节点,一边在当前节点上删除子节点,将当前节点 push 到空数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function flatten1(tree) {
var arr = [];
function spread(tree, pid) {
for (var i = 0; i < tree.length; i++) {
ele = tree[i];
let { children, ...item } = ele;
arr.push({ ...item, pid });
if (ele.children) {
spread(ele.children, ele.id);
delete ele.children;
}
}
}
spread(tree, 0);
return arr;
}

newArr = flatten1(tree);

思路二:

1
2
3
4
5
6
7
8
function flatten2(data, pid) {
return data.reduce((arr, currentValue) => {
let { children, ...item } = currentValue;
return arr.concat([{ ...item, pid }], flatten2(children, item.id));
}, []);
}

newArr = flatten2(tree, "");

结果如下:

树形结构转换为有父子关系属性的数组结构

将数组结构转换为树形结构

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function treeData(arr, pname = "pid") {
return (function recursion(pid) {
const data = [];
arr.forEach((element) => {
const id = element[pname];
if ((!pid && !id) || pid == element[pname]) {
const children = recursion(element.id);
data.push(
Object.assign(
element,
children.length
? {
children
}
: {}
)
);
}
});
return data;
})();
}
1
2
3
4
5
6
7
8
9
10
function treeData(data, pname = "pid", cname = "id") {
let cloneData = JSON.parse(JSON.stringify(data));
return cloneData.filter((parent) => {
let branchArr = cloneData.filter((child) => parent[cname] == child[pname] && child[cname] != child[pname]);
branchArr.length > 0 ? (parent["children"] = branchArr) : "";
return parent[pname] == 0;
});
}

newTree = treeData(newArr);

递归实例:阶乘

1
2
3
4
5
6
7
8
function factorial(n) {
if (n === 0) {
return 1;
}
return n * factorial(n - 1);
}

factorial(4); // 4 * factorial(3) = 24