Javascript tree search algorithm which return subset of the tree which contains the found term and its parents

白昼怎懂夜的黑 提交于 2020-03-28 03:57:12

问题


I have a tree selection in which every node has a name. I want to search through the node names and return a subset of the tree which only contains the found nodes and its parents.

Does anybody know an efficient algorithm in JavaScript for this problem which return the node with all of its parents.

Here is an example. when user type a search term, example "Elephant" and the tree looks like this:

  • Elephant
    • Hamster
      • Fish
    • Duck
  • Hamster
    • dog
      • Fish
    • Elephant
      • Fish
  • Dog
    • Fish
      • Unicorn
        • Elephant
      • Elephant
      • Hamster
    • Unicorn
  • Elephant
    • Hamster
      • Fish
      • Elephant
      • Elephant
    • Elephant

Would like to output the search result in tree format with children like this:

  • Elephant
  • Hamster
    • Elephant
  • Dog
    • Fish
      • Unicorn
        • Elephant
      • Elephant
  • Elephant
    • Hamster
      • Elephant
      • Elephant
    • Elephant

Given:

this.tree =[
 {childs: Array(2), id: 2, name: "Elephant",  …}
 {childs: Array(2), id: 3, name: "Hamster", ...}
 {childs: Array(2), id: 3, name: "Dog", ...}
 {childs: Array(2), id: 3, name: "Elephant", ...}
]

Given

//  animal target name
target = 'Elephant',

//  tree data structure
tree = [
    { name: 'Elephant', childs: [
        { name: 'Duck' },
        { name: 'Hamster', childs: [
            { name: 'Fish' }
        ]}
    ]},
    { name: 'Hamster', childs: [
        { name: 'Elephant', childs: [
            { name: 'Fish' }
        ]},
        { name: 'Dog', childs: [
            { name: 'Fish' }
        ]}
    ]},
    { name: 'Dog', childs: [
        { name: 'Unicorn' },
        { name: 'Fish', childs: [
            { name: 'Hamster' },
            { name: 'Unicorn', childs: [
                { name: 'Elephant' }
            ]},
        ]}
    ]},
    { name: 'Elephant', childs: [
        { name: 'Duck' },
        { name: 'Hamster', childs: [
            { name: 'Elephant' },
            { name: 'Fish' },
        ]}
    ]}
],

Attempt to modify the tree from Nave's solution (output result in original tree object format, set property to display = false to hide the node, keep on searching the other node in the same level even if found matching node). This seems like a DFS, however am still taking lots of time to figure the backtracking. Final result is to return the tree which contains only the matching result and its parent/ancestor.

searchHelper(term, children, showParent) {
    let found;
    if (showParent == null || showParent == undefined) {
        showParent = false;
    }
    children.forEach(child => {
        if (found = this.search(term, child)){
            console.log('found--------------------------------');
            child.display = true;
        } else {
            console.log('not foond-----------------------------------------')
            child.display = false;
        }
        showParent = showParent || found;
    })
    return showParent;
}

search(term, parent) {
    let ans, showParent, found, { name, children } = parent;

    if (children.length) {
        showParent = this.searchHelper(term, children, showParent);
    }
    return name.toLowerCase().indexOf(term.toLowerCase()) != -1;
}

this.search("Elephant", this.tree);

回答1:


I guess that's what you're looking for:

search = node => {
    let found, { name, childs = [] } = node;

    if (childs.length)
        for (let child of node.childs)
            if (found = search(child))
                return [name].concat(found);

    return name === target && [name];
}

And here is my full solution:

const
    // Your animal target name
    target = 'Elephant',

    // Your tree data structure
    tree = [
        { name: 'Elephant', childs: [
            { name: 'Duck' },
            { name: 'Hamster', childs: [
                { name: 'Fish' }
            ]}
        ]},
        { name: 'Hamster', childs: [
            { name: 'Elephant', childs: [
                { name: 'Fish' }
            ]},
            { name: 'Dog', childs: [
                { name: 'Fish' }
            ]}
        ]},
        { name: 'Dog', childs: [
            { name: 'Unicorn' },
            { name: 'Fish', childs: [
                { name: 'Hamster' },
                { name: 'Unicorn', childs: [
                    { name: 'Elephant' }
                ]},
            ]}
        ]},
        { name: 'Elephant', childs: [
            { name: 'Duck' },
            { name: 'Hamster', childs: [
                { name: 'Elephant' },
                { name: 'Fish' },
            ]}
        ]}
    ],

    // The recursive tree search function. Her exit point is
    // a child who matches the target. He returns the path to
    // target - if found - as an array. Otherwise, false
    search = node => {
        let found, { name, childs = [] } = node;

        if (childs.length)
            for (let child of node.childs)
                if (found = search(child))
                    return [name].concat(found);

        return name === target && [name];
    },

    // The result, as a set of arrays. We filter out the
    // branches that do not contain the result
    result = tree.map(search).filter(Boolean);

    // The result as a formatted string for easy viewing
    formattedResult = result.map((path, index) => `${index + 1}: ${path.join(' > ')}`).join('\n');

console.log(formattedResult);


来源:https://stackoverflow.com/questions/60102867/javascript-tree-search-algorithm-which-return-subset-of-the-tree-which-contains

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!