как найти вложенный объект и вернуть все совпадающие потомки и его родителя / предка в одном формате - PullRequest
0 голосов
/ 09 февраля 2020

У меня есть поле ввода поиска, когда пользователь вводит поисковое значение, он будет искать следующий вложенный объект и выводить всех совпадающих дочерних элементов и всех совпадающих дочерних родителей и предков в формате вложенных объектов.


Древовидная структура с детьми:


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;
        }, {});
    }

``


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...