There are similar answers here but all of the ones I've seen and tested don't go pass two levels deep, so I don't think this is a duplicate problem...I am trying to filter an array of objects. Each of its objects can have other nested objects of unknown depth. For my data, treeView is a collection of treeData, and treeNode(children) will have the same interface.
export interface TreeView = TreeData[]
export interface TreeData {
label: string;
children?: TreeData[]
}
const treeData =
[
{label: 'obj-1', children: [ {label: 'bananas'},{label: 'apples', children: [
{label: 'bananas',},{label: 'apples'}, {label: 'coconut', children: [
{label: 'bananas'},{label: 'oranges', },
]},
]}]},
{label: 'obj-2', children: [ {label: 'apples'},{label: 'apples', children: [
{label: 'oranges',},{label: 'apples'}, {label: 'coconut', children: [
{label: 'bananas'},{label: 'oranges', children: [
{label: 'bananas'},{label: 'oranges', },
] },
]},
]}]},
{label: 'obj-3', children: [ {label: 'apples'},{label: 'mango'},{label: 'apples', children: [
{label: 'oranges',},{label: 'apples'}, {label: 'coconut', children: [
{label: 'bananas'},{label: 'oranges', children: [
{label: 'bananas'},{label: 'mango', },
] },
]},
]}]},
]
Objects with a label that don't match the searchTerm should be removed, and if an object has a children property, repeat the process. I've been trying to solve this with recursion. Here's my code...
const recurse = (array, searchTerm) => {
return array.map((element) => {
return {...element, subElements: element.subElements.filter((subElement) => subElement.label === searchTerm)}
})
}
const filterArray = (myArray,value) => {
for(let i = 0; i < myArray.length;i ){
if(myArray.children){
if(myArray[i].children){
filterArray(myArray[i].children,value)
}
}
}
recurse(myArray,value)
}
console.log(filterArray(treeData,'bananas'))
In the example above, searching 'bananas' would filter the entire array as many level deep as necessary, removing any objects whose label prop does not equal bananas; if an object does not have children, is its label prop equal to the search term, if not remove it from its parent array. Thanks so much in advance!
I want to return the filtered version of the original array.Only objects with 'bananas' as their label should show here
CodePudding user response:
I think you'll want something like this:
const filterByLabel = (array, searchTerm) => {
return array.reduce((prev, curr) => {
const children = curr.children ? filterByLabel(curr.children, searchTerm) : undefined;
return curr.label === searchTerm || children?.length > 0 ? [...prev, { ...curr, children }] : prev;
}, []);
}
filterByLabel(treeData, 'bananas');