如果对象与任何选定的 ID 都不匹配,则从嵌套树中移除对象
Remove object from nested tree if it doesn't match any of the selected id
我有一个选定的数组
this.selectedArray = ["1:Tree", "2:PT", "5:PT - DD", "11:PT - C", "3:SAC", "7:SAC - DR", "6:SAC - DDE"]
和具有子项的树结构:
this.root =
{"children": [
{"children": [
{
"children": [],
"id": 12,
"name": "PT - D"
},
{
"children": [
{
"children": [],
"id": 8,
"name": "PT-33"
},
{
"children": [],
"id": 10,
"name": "PT-62"
},
{
"children": [],
"id": 9,
"name": "PT-52"
}
],
"id": 4,
"name": "PT - 32"
},
{
"children": [
{
"children": [],
"id": 11,
"name": "PT - C"
}
],
"id": 5,
"name": "PT - DD"
}
],
"id": 2,
"name": "PT"
},
{
"children": [
{
"children": [],
"id": 7,
"name": "SAC - DR"
},
{
"children": [],
"id": 6,
"name": "SAC - DE"
}
],
"id": 3,
"name": "SAC"
}
],
"id": 1,
"name": "Tree"
}
如果 node.Id + ':' + node.name 与 this.selectedArray 中的任何项目都不匹配,我想从树中删除该节点。
我无法找到一种算法,该算法允许我从深度嵌套的树中删除与 this.selected 中的任何项目都不匹配的所有对象数据。
代码如下:
setSearchResult(selectedArray) {
if (!!selected) {
let this.tree = JSON.parse(JSON.stringify(this.root));
this.topLevelGroups = this.removeFromTree(this.tree, selectedArray, null, null);
}
}
removeFromTree(parent, selectedArray, grandParent, idx) {
let { name, id, children } = parent;
let parentId = id + ':' + name;
if (!!selectedArray) {
if (!selectedArray.includes(parentId)) {
if (grandParent) {
grandParent.children.splice(idx, 1);
}
else return null;
}
if (!!parent && !!children) {
for (let i = 0; i < children.length; i++) {
this.removeFromTree(children[i], selectedArray, parent, i);
}
}
}
return this.tree.children;
}
我认为问题是在执行具有 this.slice 的代码后,它将 return 并且不会转到其兄弟。有什么建议吗?
一个简单的递归过滤函数,因为你在你的selectedArray
中使用字符串你可以很容易地使用Set
来测试
一个节点。
const tags = new Set(selectedArray);
function filterArray ({ children, id, name }) {
const tag = `${id}:${name}`;
if (tags.has(tag)) {
return {
id,
name,
children: children.map(filterArray).filter((child) => child !== null)
};
}
return null;
}
const output = filterArray(root);
console.log(JSON.stringify(output, null, 4));
您可以采用非变异方法并通过尊重子项来减少数组。
此解决方案将所需 id
的散列 table 作为键,将 name
作为 selected
数组拆分值中的值。
结果只包含已知节点。
const
filter = (r, { children = [], ...o }) => {
if (nodes[o.id] !== o.name) return r;
children = children.reduce(filter, []);
r.push(children.length ? { ...o, children } : o);
return r;
},
selected = ["1:Tree", "2:PT", "5:PT - DD", "11:PT - C", "3:SAC", "7:SAC - DR", "6:SAC - DDE"],
nodes = selected.reduce((r, s) => {
var [k, v] = s.split(':');
r[k] = v;
return r;
}, {}),
tree = { children: [{ children: [{ children: [], id: 12, name: "PT - D" }, { children: [{ children: [], id: 8, name: "PT-33" }, { children: [], id: 10, name: "PT-62" }, { children: [], id: 9, name: "PT-52" }], id: 4, name: "PT - 32" }, { children: [{ children: [], id: 11, name: "PT - C" }], id: 5, name: "PT - DD" }], id: 2, name: "PT" }, { children: [{ children: [], id: 7, name: "SAC - DR" }, { children: [], id: 6, name: "SAC - DE" }], id: 3, name: "SAC" }], id: 1, name: "Tree" },
result = tree.children = tree.children.reduce(filter, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我有一个选定的数组
this.selectedArray = ["1:Tree", "2:PT", "5:PT - DD", "11:PT - C", "3:SAC", "7:SAC - DR", "6:SAC - DDE"]
和具有子项的树结构:
this.root =
{"children": [
{"children": [
{
"children": [],
"id": 12,
"name": "PT - D"
},
{
"children": [
{
"children": [],
"id": 8,
"name": "PT-33"
},
{
"children": [],
"id": 10,
"name": "PT-62"
},
{
"children": [],
"id": 9,
"name": "PT-52"
}
],
"id": 4,
"name": "PT - 32"
},
{
"children": [
{
"children": [],
"id": 11,
"name": "PT - C"
}
],
"id": 5,
"name": "PT - DD"
}
],
"id": 2,
"name": "PT"
},
{
"children": [
{
"children": [],
"id": 7,
"name": "SAC - DR"
},
{
"children": [],
"id": 6,
"name": "SAC - DE"
}
],
"id": 3,
"name": "SAC"
}
],
"id": 1,
"name": "Tree"
}
如果 node.Id + ':' + node.name 与 this.selectedArray 中的任何项目都不匹配,我想从树中删除该节点。
我无法找到一种算法,该算法允许我从深度嵌套的树中删除与 this.selected 中的任何项目都不匹配的所有对象数据。
代码如下:
setSearchResult(selectedArray) {
if (!!selected) {
let this.tree = JSON.parse(JSON.stringify(this.root));
this.topLevelGroups = this.removeFromTree(this.tree, selectedArray, null, null);
}
}
removeFromTree(parent, selectedArray, grandParent, idx) {
let { name, id, children } = parent;
let parentId = id + ':' + name;
if (!!selectedArray) {
if (!selectedArray.includes(parentId)) {
if (grandParent) {
grandParent.children.splice(idx, 1);
}
else return null;
}
if (!!parent && !!children) {
for (let i = 0; i < children.length; i++) {
this.removeFromTree(children[i], selectedArray, parent, i);
}
}
}
return this.tree.children;
}
我认为问题是在执行具有 this.slice 的代码后,它将 return 并且不会转到其兄弟。有什么建议吗?
一个简单的递归过滤函数,因为你在你的selectedArray
中使用字符串你可以很容易地使用Set
来测试
一个节点。
const tags = new Set(selectedArray);
function filterArray ({ children, id, name }) {
const tag = `${id}:${name}`;
if (tags.has(tag)) {
return {
id,
name,
children: children.map(filterArray).filter((child) => child !== null)
};
}
return null;
}
const output = filterArray(root);
console.log(JSON.stringify(output, null, 4));
您可以采用非变异方法并通过尊重子项来减少数组。
此解决方案将所需 id
的散列 table 作为键,将 name
作为 selected
数组拆分值中的值。
结果只包含已知节点。
const
filter = (r, { children = [], ...o }) => {
if (nodes[o.id] !== o.name) return r;
children = children.reduce(filter, []);
r.push(children.length ? { ...o, children } : o);
return r;
},
selected = ["1:Tree", "2:PT", "5:PT - DD", "11:PT - C", "3:SAC", "7:SAC - DR", "6:SAC - DDE"],
nodes = selected.reduce((r, s) => {
var [k, v] = s.split(':');
r[k] = v;
return r;
}, {}),
tree = { children: [{ children: [{ children: [], id: 12, name: "PT - D" }, { children: [{ children: [], id: 8, name: "PT-33" }, { children: [], id: 10, name: "PT-62" }, { children: [], id: 9, name: "PT-52" }], id: 4, name: "PT - 32" }, { children: [{ children: [], id: 11, name: "PT - C" }], id: 5, name: "PT - DD" }], id: 2, name: "PT" }, { children: [{ children: [], id: 7, name: "SAC - DR" }, { children: [], id: 6, name: "SAC - DE" }], id: 3, name: "SAC" }], id: 1, name: "Tree" },
result = tree.children = tree.children.reduce(filter, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }