I have an array of objects in the hierarchical data structure. I need to check if any of the parents or children nodes contains a search string. I am able to filter the array, but I just want to update the matchFound property instead of applying the filter on the tree data.
Expected Result: If match is found, matchFound property of all the parent and children nodes should be true otherwise false.
treeData = [{
name: 'Infiniti',
matchFound: null,
children: [{
name: 'G50',
matchFound: null,
children: [{
name: 'Pure AWD',
matchFound: null,
},
{
name: 'Luxe',
matchFound: null,
},
],
},
{
name: 'QX50',
matchFound: null,
children: [{
name: 'Pure AWD',
matchFound: null,
},
{
name: 'Luxe',
matchFound: null,
},
],
},
],
},
{
name: 'BMW',
matchFound: null,
children: [{
name: '2 Series',
matchFound: null,
children: [{
name: 'Coupé',
matchFound: null,
},
{
name: 'Gran Coupé',
matchFound: null,
},
],
},
{
name: '3 Series',
matchFound: null,
children: [{
name: 'Sedan',
matchFound: null,
},
{
name: 'PHEV',
matchFound: null,
},
],
},
],
},
];
filteredData = [];
function filter(searchString) {
this.filteredData = this.search(this.treeData, searchString);
console.log(this.filteredData)
}
function search(children, searchString) {
return children.reduce((acc, item) => {
if (item.name.toLowerCase().includes(searchString.toLowerCase())) {
acc.push(item);
} else if (item.children && item.children.length > 0) {
const newItems = this.search(item.children, searchString);
if (newItems.length > 0) {
acc.push({
name: item.name,
children: newItems
});
}
}
return acc;
}, []);
}
this.filter('infiniti');
this.filter('luxe');
CodePudding user response:
I can propose a solution wiht some assumptions:
The filter method should return new tree structure, and should not modify the original one
If any of the child nodes has match - all the parents are marked as matchFound=true
Here is a working playground
And I'll paste the meaningful parts of the code:
function filter(searchString: string) {
return treeData.map(node => search(node, searchString));
}
function search(node: CarNode, searchString: string, foundInParent = false): CarNode {
const matchFoundInNodeOrParent = foundInParent || node.name.toLowerCase().includes(searchString.toLowerCase());
const children = node?.children?.map(child => search(child, searchString ,matchFoundInNodeOrParent));
//match is found if parent or this node or at least one of th children has mathc found
const matchFound = matchFoundInNodeOrParent || ( children !== undefined && children.some(child => child.matchFound));
//return new object
return children !== undefined ? { ...node, matchFound, children } : { ...node, matchFound };
}