合并两棵树仅将唯一节点从一棵树添加到下一棵树
merge two trees adding only unique nodes from one tree to the next
我正在尝试将 Tree2 合并到 Tree1 中。合并结果包含 Tree1 中的所有现有节点以及 Tree2 节点,这些节点位于层次结构中的正确级别,这些节点在 Tree1 中不存在。最终的树输入更大更深,但我一直在努力处理下面的简单示例树。
Tree1 = {"name":"A","children":[{"name":"B","children":[{"name":"C","children":[]}]},"name":"B1","children":[{"name":"C1","children":[]}]}]}
Tree2 = {"name":"A", "children":[{"name":"B", "children":[{"name":"C2", "children":[]}]}]}
merged = {"name":"A","children":[{"name":"B","children":[{"name":"C","children":[]},{"name":"C2","children":[]}]},{"name":"B1","children":[{"name":"C1","children":[]}]}]}
可以通过查看同级别的名字属性来合并
这种方法returns一个数组,因为如果你对根有不同的名字,结果至少包含两个对象。
const
merge = (a, b) => {
if (!Array.isArray(a)) a = [a];
if (!Array.isArray(b)) b = [b];
return [...a, ...b].reduce((r, o) => {
const item = r.find(({ name }) => o.name === name);
if (item) item.children = merge(item.children, o.children);
else r.push(o);
return r;
}, []);
},
tree1 = { name: "A", children: [{ name: "B", children: [{ name: "C", children: [] }] }, { name: "B1", children: [{ name: "C1", children: [] }] }] },
tree2 = { name: "A", children: [{ name: "B", children: [{ name: "C2", children: [] }] }] },
result = merge(tree1, tree2);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以使用递归来合并您的树:
function merge(...trees){
var m = {};
for (var i of trees){
m[i.name] = [...(i.name in m ? m[i.name] : []), ...i.children];
}
return Object.keys(m).map(function(x){return {name:x, children:m[x].length > 1 ? merge(...m[x]) : m[x]}})
}
我们注意到 children 的收集列表与我们函数的初始参数的相似性,并且可以以简单的递归结束。在这里,我们将树折叠成 object,其键是 name
,其值是收集到的 children。然后我们调用 Object .entries
并将 key-value 对映射到 name
和(通过递归调用)每个的 children
属性。仅此而已
const mergeTrees = (...trees) =>
Object .entries (trees .reduce ((a, {name, children = []}) => ({
...a,
[name]: (a [name] || []) .concat (children)
}), {})) .map (([k, v]) => ({name: k, children : mergeTrees (...v)}))
const tree1 = {name: "A", children: [{name: "B", children: [{name: "C", children: []}]}, {name: "B1", children: [{name: "C1", children: []}]}]}
const tree2 = {name: "A", children: [{name: "B", children: [{name: "C2", children: []}]}]}
console .log (mergeTrees (tree1, tree2))
.as-console-wrapper {max-height: 100% !important; top: 0}
请注意,我们 return 是一片森林,而不是一棵树。如果你知道所有的树都有相同的根,那么你可以从结果中提取第一个元素。
我正在尝试将 Tree2 合并到 Tree1 中。合并结果包含 Tree1 中的所有现有节点以及 Tree2 节点,这些节点位于层次结构中的正确级别,这些节点在 Tree1 中不存在。最终的树输入更大更深,但我一直在努力处理下面的简单示例树。
Tree1 = {"name":"A","children":[{"name":"B","children":[{"name":"C","children":[]}]},"name":"B1","children":[{"name":"C1","children":[]}]}]}
Tree2 = {"name":"A", "children":[{"name":"B", "children":[{"name":"C2", "children":[]}]}]}
merged = {"name":"A","children":[{"name":"B","children":[{"name":"C","children":[]},{"name":"C2","children":[]}]},{"name":"B1","children":[{"name":"C1","children":[]}]}]}
可以通过查看同级别的名字属性来合并
这种方法returns一个数组,因为如果你对根有不同的名字,结果至少包含两个对象。
const
merge = (a, b) => {
if (!Array.isArray(a)) a = [a];
if (!Array.isArray(b)) b = [b];
return [...a, ...b].reduce((r, o) => {
const item = r.find(({ name }) => o.name === name);
if (item) item.children = merge(item.children, o.children);
else r.push(o);
return r;
}, []);
},
tree1 = { name: "A", children: [{ name: "B", children: [{ name: "C", children: [] }] }, { name: "B1", children: [{ name: "C1", children: [] }] }] },
tree2 = { name: "A", children: [{ name: "B", children: [{ name: "C2", children: [] }] }] },
result = merge(tree1, tree2);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以使用递归来合并您的树:
function merge(...trees){
var m = {};
for (var i of trees){
m[i.name] = [...(i.name in m ? m[i.name] : []), ...i.children];
}
return Object.keys(m).map(function(x){return {name:x, children:m[x].length > 1 ? merge(...m[x]) : m[x]}})
}
我们注意到 children 的收集列表与我们函数的初始参数的相似性,并且可以以简单的递归结束。在这里,我们将树折叠成 object,其键是 name
,其值是收集到的 children。然后我们调用 Object .entries
并将 key-value 对映射到 name
和(通过递归调用)每个的 children
属性。仅此而已
const mergeTrees = (...trees) =>
Object .entries (trees .reduce ((a, {name, children = []}) => ({
...a,
[name]: (a [name] || []) .concat (children)
}), {})) .map (([k, v]) => ({name: k, children : mergeTrees (...v)}))
const tree1 = {name: "A", children: [{name: "B", children: [{name: "C", children: []}]}, {name: "B1", children: [{name: "C1", children: []}]}]}
const tree2 = {name: "A", children: [{name: "B", children: [{name: "C2", children: []}]}]}
console .log (mergeTrees (tree1, tree2))
.as-console-wrapper {max-height: 100% !important; top: 0}
请注意,我们 return 是一片森林,而不是一棵树。如果你知道所有的树都有相同的根,那么你可以从结果中提取第一个元素。