Javascript 树视图搜索

Javascript Tree view Search

我正在尝试使用 JavaScript 实现树视图搜索。我发现 很有用,但提供的答案在我的场景中没有预期的输出。

示例输入:

[
    {
        "id": 1,
        "templateName": "Item 1",
        "isFolder": "true",
        "children": [
            {
                "id": 2,
                "templateName": "Subitem 1",
                "isFolder": "true",
                "children": [
                    {
                        "id": 3,
                        "templateName": "Misc 1",
                        "isFolder": "true",
                        "children": [
                            {
                                "id": 4,
                                "templateName": "Misc 2"
                            }
                        ]
                    }
                ]
            },
            {
                "id": 5,
                "templateName": "Subitem 2",
                "isFolder": "true",
                "children": [
                    {
                        "id": 6,
                        "templateName": "Misc 3"
                    }
                ]
            }
        ]
    },
    {
        "id": 7,
        "templateName": "Item 2",
        "isFolder": "true",
        "children": [
            {   
                "id": 8,
                "templateName": "Subitem 1",
                "isFolder": "true",
                "children": [
                    {
                        "id": 9,
                        "templateName": "Misc 1"
                    }
                ]
            },
            {
                "id": 10,
                "templateName": "Subitem 8",
                "isFolder": "true",
                "children": [
                    {
                        "id": 11,
                        "templateName": "Misc 4"
                    },
                    {
                        "id": 12,
                        "templateName": "Misc 5"
                    },
                    {
                        "id": 13,
                        "templateName": "Misc 6",
                        "isFolder": "true",
                        "children": [
                            {
                                "id": 14,
                                "templateName": "Misc 7"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

如果我搜索 Subitem 1,那么预期的输出是:

[
    {
        "id": 1,
        "templateName": "Item 1",
        "isFolder": "true",
        "children": [
            {
                "id": 2,
                "templateName": "Subitem 1",
                "isFolder": "true",
                "children": [
                    {
                        "id": 3,
                        "templateName": "Misc 1",
                        "isFolder": "true",
                        "children": [
                            {
                                "id": 4,
                                "templateName": "Misc 2"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "id": 7,
        "templateName": "Item 2",
        "isFolder": "true",
        "children": [
            {   
                "id": 8,
                "templateName": "Subitem 1",
                "isFolder": "true",
                "children": [
                    {
                        "id": 9,
                        "templateName": "Misc 1"
                    }
                ]
            }
        ]
    }
]

但引用的问答中的答案 returns 对象没有 children 属性。

我尝试修改该答案的代码,还添加了 isFolder 道具以进行额外验证以帮助我。但是我无法return上面的预期输出。

您可以使用复制树的递归函数来执行此操作,但只保留具有更深匹配的子项。当一个节点匹配时,不需要更深层次的递归,因为该节点下的整个子树仍然包含在内。

这里我用了map和一个链式的filter(Boolean)。您可以使用 reduce 实现相同的效果。当以该节点为根的子树中某处没有匹配项时,map 会将节点映射到 false。这些 false 值然后被 filter(Boolean):

消除

function deepFilter(nodes, cb) {
    return nodes.map(node => {
        if (cb(node)) return node;
        let children = deepFilter(node.children || [], cb);
        return children.length && { ...node,  children };
    }).filter(Boolean);
}

const forest = [{"id": 1,"templateName": "Item 1","isFolder": "true","children": [{"id": 2,"templateName": "Subitem 1","isFolder": "true","children": [{"id": 3,"templateName": "Misc 1","isFolder": "true","children": [{"id": 4,"templateName": "Misc 2"}]}]},{"id": 5,"templateName": "Subitem 2","isFolder": "true","children": [{"id": 6,"templateName": "Misc 3"}]}]},{"id": 7,"templateName": "Item 2","isFolder": "true","children": [{"id": 8,"templateName": "Subitem 1","isFolder": "true","children": [{"id": 9,"templateName": "Misc 1"}]},{"id": 10,"templateName": "Subitem 8","isFolder": "true","children": [{"id": 11,"templateName": "Misc 4"},{"id": 12,"templateName": "Misc 5"},{"id": 13,"templateName": "Misc 6","isFolder": "true","children": [{"id": 14,"templateName": "Misc 7"}]}]}]}];

const result = deepFilter(forest, node =>
    node.templateName.includes("Subitem 1")
);

console.log(result);