I have a selected array
this.selectedArray = ["1:Tree", "2:PT", "5:PT - DD", "11:PT - C", "3:SAC", "7:SAC - DR", "6:SAC - DDE"]
and Tree structure with children:
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"
}
I would like to remove the node from the tree if the node.Id + ':' + node.name doesn't match any of the items in this.selectedArray.
I am having trouble finding an algorithm that will allow me to delete all the object data which doesn't match any of the item in this.selected from the deeply nested tree.
Here is the code:
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;
}
I think the problem is after executing code which has this.slice, it will return and doesn't go to its sibling. Any suggestions on that?
You could take a nonmutating approach and reduce the array by respecting the children.
This solution takes a hash table for the wanted id
as key and name
as value from the splitted values of the selected
array.
As result only known nodes are included.
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; }