我有一个对象数组。这些对象可以是根元素或列表元素(树结构的元素)。如何遍历该数组将那些元素组织成深度为n(未知)的树(对象具有其父元素的属性-id)?
我正在尝试构建(菜单)。我已经成功地将列表元素组织到了他们的父母中。但我坚持将所有根元素放入其父母(或根)中。我遇到的问题是它没有嵌套循环(检查何时组织了一切)。
起始数据示例:https://pastebin.com/eCSZ1HgR
[
{
"groupId": 1,
"parentGroupId": null
},
{
"groupId": 3,
"parentGroupId": 1
}, ...
]
如果对象parentGroupId为null,则表示它位于树的根中。
当前,我正在使用以下代码:
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;
}
}
}
答案 0 :(得分:1)
使用Array.prototype.reduce和Array.prototype.filter函数非常简单
const tree = groups.reduce((acc, group) => {
group.children = groups.filter(g => g.parentGroupId === group.groupId);
acc.push(group);
return acc;
}, []).filter(g => g.parentGroupId === null);
答案 1 :(得分:0)
这是进行深度复制的一种方法:
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");