javascript - 元素重复时如何将节点树合并为一棵
问题描述
我该如何解决必须合并具有重复值的树的情况?例如这样的:
const firstTree = {
id: 1,
name: 'name1',
otherProperty: 'property1',
children: [
{
id: '1a',
name: 'name1a',
otherProperty: 'property1a',
children: []
},
{
id: '1b',
name: 'name1b',
otherProperty: 'property1b',
children: [
{
id: '1ba',
name: 'name1ba',
otherProperty: 'property1ba',
children: []
},
{
id: '1bb',
name: 'name1bb',
otherProperty: 'property1bb',
children: []
}
]
}
]
};
const secondTree = {
id: 1,
name: 'name1',
otherProperty: 'property1',
children: [
{
id: '1b',
name: 'name1b',
otherProperty: 'property1b',
children: [
{
id: '1ba',
name: 'name1ba',
otherProperty: 'property1ba',
children: []
},
{
id: '2ba',
name: 'name2ba',
otherProperty: 'property2ba',
children: []
}
]
}
]
};
const thirdTree = {
id: '3',
name: 'name3',
otherProperty: 'property3',
children: [
{
id: '3a',
name: 'name3a',
otherProperty: 'property3a',
children: []
},
{
id: '3b',
name: 'name3b',
otherProperty: 'property3b',
children: []
}
]
};
const entryArray = [firstTree, secondTree, thirdTree];
因此,我希望将第一棵树与第二棵树合并,并将第三棵树合并,其中没有共同的元素:
const mergedFirstAndSecond = {
id: 1,
name: 'name1',
otherProperty: 'property1',
children: [
{
id: '1a',
name: 'name1a',
otherProperty: 'property1a',
children: []
},
{
id: '1b',
name: 'name1b',
otherProperty: 'property1b',
children: [
{
id: '1ba',
name: 'name1ba',
otherProperty: 'property1ba',
children: []
},
{
id: '1bb',
name: 'name1bb',
otherProperty: 'property1bb',
children: []
},
{
id: '2ba',
name: 'name2ba',
otherProperty: 'property2ba',
children: []
}
]
}
]
};
const result = [mergedFirstAndSecond, thirdTree];
我的意思是,如果重复元素也出现在三个不同的树中,而不仅仅是两个,那么这个解决方案也可以工作。我将非常感谢任何建议。
解决方案
您可以使用递归来合并它们id
s 上的树:
var firstTree = {'id': 1, 'name': 'name1', 'otherProperty': 'property1', 'children': [{'id': '1a', 'name': 'name1a', 'otherProperty': 'property1a', 'children': []}, {'id': '1b', 'name': 'name1b', 'otherProperty': 'property1b', 'children': [{'id': '1ba', 'name': 'name1ba', 'otherProperty': 'property1ba', 'children': []}, {'id': '1bb', 'name': 'name1bb', 'otherProperty': 'property1bb', 'children': []}]}]};
var secondTree = {'id': 1, 'name': 'name1', 'otherProperty': 'property1', 'children': [{'id': '1b', 'name': 'name1b', 'otherProperty': 'property1b', 'children': [{'id': '1ba', 'name': 'name1ba', 'otherProperty': 'property1ba', 'children': []}, {'id': '2ba', 'name': 'name2ba', 'otherProperty': 'property2ba', 'children': []}]}]};
var thirdTree = {'id': '3', 'name': 'name3', 'otherProperty': 'property3', 'children': [{'id': '3a', 'name': 'name3a', 'otherProperty': 'property3a', 'children': []}, {'id': '3b', 'name': 'name3b', 'otherProperty': 'property3b', 'children': []}]};
var entryArray = [firstTree, secondTree, thirdTree];
function merge_trees(trees){
var merger = {};
//find matches based on id
for (var t of trees){
for (var i of t){
if (!(i['id'] in merger)){
merger[i['id']] = Object.fromEntries(Object.keys(i).map(x => [x, (new Set([i[x]]))]));
}
for (var k of Object.keys(i)){
merger[i['id']][k] = new Set([...(k in merger[i['id']] ? merger[i['id']][k] : []), i[k]]);
}
}
}
var new_result = [];
//iterate over merges
for (var i of Object.keys(merger)){
var result = {}
for (var k of Object.keys(merger[i])){
//choose whether or not to merge again based on the size of the merged children
if (k === 'children'){
result[k] = merger[i][k].size > 1 ? merge_trees(merger[i][k]) : [...merger[i][k]].filter(x => x.length > 1)
}
else{
result[k] = merger[i][k].size === 1 ? [...merger[i][k]][0] : [...merger[i][k]]
}
}
new_result.push(result)
}
return new_result;
}
console.log(merge_trees(entryArray.map(x => [x])))
推荐阅读
- r - 未提供汇总函数,默认为 `mean_se()`
- c++ - Anaconda 是否有任何用于 C++ 的 PCL 库以在 Windows 中使用?
- c - 这是我的代码的简化版本。我的输出有问题。我该如何解决?
- javascript - 如何仅将像“HH:MM:SS”这样的时间转换为javascript中的纪元?
- java - 在 Eclipse git staging 中向上箭头
- java - 在 EJB 中重新启动窗口后的 javax.naming.NameNotFoundException
- git - Git Bisect 提交列表
- python-3.x - Python:从文件中获取输入并将其存储为 int 数据类型
- c++ - 'const' 关键字改变语义
- excel - 我正在尝试调整代码以适应未找到搜索项目的情况