У меня есть поле ввода поиска, когда пользователь вводит поисковое значение, он будет искать следующий вложенный объект и выводить всех совпадающих дочерних элементов и всех совпадающих дочерних родителей и предков в формате вложенных объектов.
Древовидная структура с детьми:
this.rootTree =
{"children": [
"id": 1,
"name": "Tree",
{
"id": 2,
"name": "PT",
"children": [
{
"children": [],
"id": 12,
"name": "PT - 62"
},
{
"id": 4,
"name": "PT - 32",
"children": [
{
"children": [],
"id": 8,
"name": "PT-33"
},
{
"children": [],
"id": 10,
"name": "PT-62"
},
{
"children": [],
"id": 9,
"name": "PT-52"
}
]
},
{
"id": 5,
"name": "PT - DD",
"children": [
{
"children": [],
"id": 11,
"name": "PT - C"
}
]
}
]
},
{
"id": 3,
"name": "SAC - 62",
"children": [
{
"children": [],
"id": 7,
"name": "SAC - DR"
},
{
"children": [],
"id": 6,
"name": "SAC - DE"
}
]
}]
}
Когда пользователь ищет '62', вывод Desire:
{
"id": 1,
"name": "Tree",
"children": [
{
"id": 2,
"name": "PT",
"children": [
{
"children": [],
"id": 12,
"name": "PT - 62"
},
{
"id": 4,
"name": "PT - 32",
"children": [
{
"children": [],
"id": 10,
"name": "PT-62"
}]
}]
},
{
"children": [],
"id": 3,
"name": "SAC - 62"
}
]
}
Следующий код работает, но задается вопросом, существует ли более простое / быстрое решение без поиск по корневому дереву дважды
// when user type '62', it will the output the result store in variable this.solution
onSearch('62');
onSearch(term) {
this.solution = [];
let foundArr = this.search(term, JSON.parse(JSON.stringify(this.rootTree)), [], []);
if (!!foundArr) {
let matchList = this.mergeDedupe(foundArr);
if (matchList.length) {
this.setSearchResult(matchList);
}
}
}
search(term, parent, path, basket) {
let { name, id, children } = parent;
let nameId = id + ':' + name;
let fork = path.slice(0);
fork.push(nameId);
if (name.toLowerCase().indexOf(term) !== -1) {
basket.push(fork);
}
if (!!children && children.length > 0) {
for (let child of parent.children) {
this.search(term, child, fork, basket)
}
return basket;
}
}
mergeDedupe(arr) {
return Array.from(new Set(Array.prototype.concat(...arr)));
}
setSearchResult(matchList) {
if (!!matchList) {
this.root = JSON.parse(JSON.stringify(this.nestedTree));
this.matchList = matchList;
this.solution = this.root.children.reduce(this.filter, []);
}
}
removeFromTree(parent, matchList, grandParent, idx) {
let { name, id, children } = parent;
let parentId = id + ':' + name;
if (!!matchList) {
if (!matchList.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], matchList, parent, i);
}
}
}
return this.root.children;
}
filter = (r, { children = [], ...o }) => {
let nodes = this.reduceNodes(this.matchList);
if (nodes[o.id] !== o.name) return r;
children = children.reduce(this.filter, []);
r.push(children.length ? { ...o, children } : o);
return r;
};
reduceNodes(selected) {
return selected.reduce((r, s) => {
var [k, v] = s.split(':');
r[k] = v;
return r;
}, {});
}
``