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
Advertisement
Answer
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');