I have the following array of objects with nested elements in the children property. I need to get objects by their id if the id matches.
[
{
"id": 10,
"name": "Scenarios",
"value": null,
"children": [
{
"id": 12,
"name": "Scenario status",
"value": null,
"children": []
}
]
},
{
"id": 11,
"name": "Forecast source",
"value": null,
"children": []
},
{
"id": 16787217,
"name": "Item@Cust",
"value": null,
"children": [
{
"id": 16787230,
"name": "Customer",
"value": null,
"children": [
{
"id": 16787265,
"name": "Site",
"value": null,
"children": []
},
{
"id": 16787291,
"name": "Commercial Network",
"value": null,
"children": []
},
{
"id": 16787296,
"name": "Distribution Site",
"value": null,
"children": []
}
]
},
{
"id": 16787245,
"name": "Item@Site",
"value": null,
"children": [
{
"id": 16787266,
"name": "Family@Warehouse",
"value": null,
"children": []
}
]
},
{
"id": 16787254,
"name": "Item",
"value": null,
"children": [
{
"id": 16787260,
"name": "Family",
"value": null,
"children": [
{
"id": 16787264,
"name": "Product line",
"value": null,
"children": []
}
]
},
{
"id": 16787261,
"name": "Group 1",
"value": null,
"children": []
}
]
}
]
},
{
"id": 16787267,
"name": "Supplier",
"value": null,
"children": []
},
{
"id": 16787297,
"name": "SKU",
"value": null,
"children": []
}
]
If no match on root element is found, the function should lookup its children to see if there is a match, and the first children match should be pushed on the root level.
For exemple, I have a list of ids: [12, 16787217, 16787245, 16787266]
The function should return only objects where ids matches while keeping hierarchy if matching parent id have matching children id, so it should return this:
[
{
"id": 12,
"name": "Scenario status",
"value": null,
"children": []
},
{
"id": 16787217,
"name": "Item@Cust",
"value": null,
"children": [
{
"id": 16787245,
"name": "Item@Site",
"value": null,
"children": [
{
"id": 16787266,
"name": "Family@Warehouse",
"value": null,
"children": []
}
]
}
]
}
]
As for now, I can get only the first level elements if they are found with this function:
filterArray(array: Array<any>, ids: Array<number>) {
array = array.filter(el => ids.includes(el.id));
for (let i = 0; i < array.length; i++) {
this.filterArray(array[i].children, ids);
}
console.log(array);
}
Anyone have an idea on how to achieve this?
You could reduce the array and take the nodes with found id and children or only the children at the base level.
const
find = (r, { children = [], ...o }) => {
children = children.reduce(find, []);
if (ids.includes(o.id)) r.push({ ...o, children });
else if (children.length) r.push(...children);
return r;
},
data = [{ id: 10, name: "Scenarios", value: null, children: [{ id: 12, name: "Scenario status", value: null, children: [] }] }, { id: 11, name: "Forecast source", value: null, children: [] }, { id: 16787217, name: "Item@Cust", value: null, children: [{ id: 16787230, name: "Customer", value: null, children: [{ id: 16787265, name: "Site", value: null, children: [] }, { id: 16787291, name: "Commercial Network", value: null, children: [] }, { id: 16787296, name: "Distribution Site", value: null, children: [] }] }, { id: 16787245, name: "Item@Site", value: null, children: [{ id: 16787266, name: "Family@Warehouse", value: null, children: [] }] }, { id: 16787254, name: "Item", value: null, children: [{ id: 16787260, name: "Family", value: null, children: [{ id: 16787264, name: "Product line", value: null, children: [] }] }, { id: 16787261, name: "Group 1", value: null, children: [] }] }] }, { id: 16787267, name: "Supplier", value: null, children: [] }, { id: 16787297, name: "SKU", value: null, children: [] }],
ids = [12, 16787217, 16787245, 16787266],
result = data.reduce(find, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }