javascript - How to organize array of objects into themselves by id
问题描述
I have an array of objects. Those objects can be root or list element (elements of a tree structure). How can I loop through that array to organize those elements into a tree (objects have property of their parent element - id) with the depth of n (not known)?
I'm trying to build (menu). I have successfully organized list elements into their parents. But I'm stuck at putting all root elements into their parents (or root). Problem that I'm having is doing it without nesting loops (checking when everything is organized).
Example of starting data: https://pastebin.com/eCSZ1HgR
[
{
"groupId": 1,
"parentGroupId": null
},
{
"groupId": 3,
"parentGroupId": 1
}, ...
]
If objects parentGroupId is null, means that it's in the root of a tree.
Currently I'm working with this code:
for (var i = 0; i < groups.length; i++) {
var childGroup = groups[i];
if (childGroup.parentGroupId === null) {
continue;
}
for (var j = 0; j < groups.length; j++) {
var parentGroup = groups[j];
if (childGroup.parentGroupId === parentGroup.groupId) {
if (parentGroup.hasOwnProperty('children')) {
parentGroup.children.push(childGroup);
} else {
parentGroup.children = [childGroup];
}
break;
}
}
}
解决方案
这是一种进行深度复制的方法:
const testInput = [
{
"groupId": 1,
"parentGroupId": null
},
{
"groupId": 3,
"parentGroupId": 1
},
{
"groupId": 4,
"parentGroupId": 3
},
{
"groupId": 5,
"parentGroupId": 1
}
];
function flatToTree(flatList, idPropName, parentPropName, childrenPropName) {
const list = [];
const listIndex = {};
/* Copy the array and create an index */
flatList.forEach(listItem => {
const objectCopy = Object.assign({}, listItem);
list.push(objectCopy);
listIndex[listItem[idPropName]] = objectCopy;
});
/* Assign children */
list.forEach(listItem => {
if (listItem[parentPropName]) {
const parent = listIndex[listItem[parentPropName]];
if (Array.isArray(parent[childrenPropName])) {
parent[childrenPropName].push(listItem);
}
else {
parent[childrenPropName] = [listItem];
}
}
});
/* Pick the root elements */
return list.filter(listItem => listItem[parentPropName] === null);
}
const testOutput = flatToTree(testInput, "groupId", "parentGroupId", "children");
推荐阅读
- r - 你能创建一个使用前缀和后缀调用的 R 函数(像括号一样操作)吗?
- glsl - WebGL fragshader ... gl_FragColor 的传入值是多少?
- reactjs - 可以将材质 UI 样式注入 iframe 吗?
- c++ - 是一种比较向量等于C++中另一个向量的一部分的方法吗?
- python - 获取多年来的平均月数
- javascript - Axios 无法发布导航器 getCurrentPosition
- sql - 为什么这个简单的 SQL 查询不起作用?从表中选择 *, count(*)
- html - 如何删除导航栏中图像的边框?
- javascript - 如何映射图像数组并将其用作 React 中的内联样式
- python - 根据值更改条形图颜色