在树结构中搜索JSON数据

时间:2017-08-07 11:45:28

标签: json angular typescript treeview

我正在使用搜索选项在树形结构中构建动态菜单。

JSON数据如下所示:

directories = [
            {
                name: 'parent1',
                child: [{
                    name: 'child1',
                    child: [{
                        name: 'child2',
                        child: []
                    }]
                },
                {
                    name: 'child2',
                    child: []
                }]
            },
            {
                name: 'parent2',
                child: [{
                    name: 'child1',
                    child: []
                }]
            },
            {
                name: 'parent2',
                child: [{
                    name: 'child1',
                    child: []
                },
                {
                    name: 'child2',
                    child: []
                }]
            }
        ];
    }

在代码下面搜索父节点级别的项目:

searchFilter(search: string) {
        console.log(search);
        this.filteredArray = this.directories.filter(item => {
            if (item.name.toString().toLowerCase().startsWith(search.toLowerCase())) {
                return true;
            }
            return false;
        }
        );
        console.log(this.filteredArray);
    }

我在keyup事件上调用上面的代码,并在父节点级别返回搜索结果。

现在我想搜索到第n个孩子。有什么帮助吗?

3 个答案:

答案 0 :(得分:1)

您需要为过滤器执行递归实现,例如:

function searchFilter(search: string, directories: any[]) {
    for(let directory of directories){
        if(directory.name.toLowerCase().startsWith(search)){
            return directory;
        }
        if (directory.child !== undefined && directory.child.length > 0) {
            let childsearch = searchFilter(search, directory.child)
            if (childsearch !== undefined) {
                return childsearch
            }
        }
    }
    return undefined;
}

see on typescript playground

另一种方法可以返回数组中的每个匹配项(就像第n个深度过滤器一样):

function searchFilter(search: string, directories: any[], results = []) {
    for(let directory of directories){
        if(directory.name.toLowerCase().startsWith(search)){
            results.push(directory);
        }
        if (directory.child !== undefined && directory.child.length > 0) {
            let childsearch = searchFilter(search, directory.child)
            if (childsearch !== undefined) {
                results = results.concat(childsearch);
            }
        }
    }
    return results;
}

see on typescript playground

答案 1 :(得分:1)

这将查看整个树的内部并提供包含所有相应结果的数组

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.dell.database, PID: 22852
              com.firebase.client.FirebaseException: Failed to bounce to type
                  at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:185)
                  at com.example.dell.database.Main2Activity$1$1.onDataChange(Main2Activity.java:60)
                  at com.firebase.client.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:45)
                  at com.firebase.client.core.view.DataEvent.fire(DataEvent.java:45)
                  at com.firebase.client.core.view.EventRaiser$1.run(EventRaiser.java:38)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:135)
                  at android.app.ActivityThread.main(ActivityThread.java:5910)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at java.lang.reflect.Method.invoke(Method.java:372)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
               Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class com.example.dell.database.Person] from String value; no single-String constructor/factory method
                  at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator._createFromStringFallbacks(StdValueInstantiator.java:428)
                  at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:299)
                  at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1056)
                  at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:136)
                  at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:123)
                  at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
                  at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
                  at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:183)
                  at com.example.dell.database.Main2Activity$1$1.onDataChange(Main2Activity.java:60) 
                  at com.firebase.client.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:45) 
                  at com.firebase.client.core.view.DataEvent.fire(DataEvent.java:45) 
                  at com.firebase.client.core.view.EventRaiser$1.run(EventRaiser.java:38) 
                  at android.os.Handler.handleCallback(Handler.java:739) 
                  at android.os.Handler.dispatchMessage(Handler.java:95) 
                  at android.os.Looper.loop(Looper.java:135) 
                  at android.app.ActivityThread.main(ActivityThread.java:5910) 
                  at java.lang.reflect.Method.invoke(Native Method) 
                  at java.lang.reflect.Method.invoke(Method.java:372) 
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405) 
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200) 

答案 2 :(得分:0)

基于@Lejendarm的答案,我这样更改:

searchFilter(search: string, directories: any[]) {
      let results = [];
       for (let directory of directories) {
          if (directory.title.toLowerCase().includes(search)) {
            results.push(directory);
          } else if (directory.child && directory.child.length > 0) {
            let foundedNodes = this.searchFilter(directory.child);
            if (foundedNodes.length > 0) {
              directory.kids = foundedNodes;
              results = results.concat([directory]);
            }
          }
          
    return results;
 }