【问题标题】:search in JSON tree with full structure intect在具有完整结构完整性的 JSON 树中搜索
【发布时间】:2019-03-02 07:35:24
【问题描述】:

我认为这是以前在这里问过的filter nested tree object without losing structure

但我正在寻找的是相反的。

对于 JSON 数据

    var items = [
    {
        name: "a1",
        id: 1,
        children: [{
            name: "a2",
            id: 2,
            children: [{
                name: "a3",
                id: 3
            }]
        },
        {
            name: "b2",
            id: 5,
            children: [{
                name: "a4",
                id: 4
            }]
        }]
    }
];

如果您搜索a2,我们需要过滤器。它应该返回以下内容

var items = [
{
    name: "a1",
    id: 1,
    children: [{
        name: "a2",
        id: 2,
        children: [{
            name: "a3",
            id: 3
        }]
    }]
}

];

即该树路径中的所有节点(从根到叶节点)。

知道如何在 nodejs/javascript 中实现吗?

谢谢

【问题讨论】:

    标签: javascript json node.js search filter


    【解决方案1】:

    按照我的示例,您可以更改代码以适合您的作品:

    var items = [
        {
            name: "a1",
            id: 1,
            children: [{
                name: "a2",
                id: 2,
                children: [{
                    name: "a3",
                    id: 3
                }]
            },
            {
                name: "b2",
                id: 5,
                children: [{
                    name: "a4",
                    id: 4
                }]
            }]
        }
    ];
    //console.log(items);
    //first, add depth (of each element) to array items
    var depths = items;
    //structure of path = [[0,length_1st],[1,length_2nd],[2,length_3rd],[3,length_4th],...,[last,length_last]]
    var path = [];
    //for first value of path
    path.push([0,depths.length]);
    //test to add depth for depths:
    depths.map(function add_depth(current){
      current['depth'] = path[path.length-1][0];
      if(current.children){
        //continue to array children
        path.push([path[path.length-1][0]+1,current.children.length]);
        current.children.map(add_depth);
      }else{
        //get back of path
        while(path.length>1 && path[path.length-1][1]<2){
            path.pop();
        }
        //decrease length path[...[x,length]]
        path[path.length-1][1]--;
      };
    });
    //console.log(depths);
    
    // has depth in array depths, now is function for search in array depths
    function search_name(str){
        let path_result = [];
        let flagExit = false;
        depths.findIndex(function find_name(current,index){
            if (flagExit){
                return;
            };
            if(current.name===str){
                //finish at here
                path_result[current.depth] = index;
                flagExit = true;
                return;
            }else{
                if(current.children){
                    path_result[current.depth] = index;
                    current.children.findIndex(find_name);
                };
            };
        });
        return path_result;
    };
    var name_to_search = "a3";
    var path_end = search_name(name_to_search); //console.log(path_end);
    //show result from path_end:
    var result = [];
    var self_items, self_result;
    if (path_end){
        for(let i=0;i<path_end.length;i++){
            if(i===0){
                result[i] = {};
                result[i]['name'] = items[path_end[i]].name;
                result[i]['id'] = items[path_end[i]].id;
                if(i === path_end.length-1){
                    //just the first result
                    result[i]['children'] = items[path_end[i]].children;
                }else{
                    result[i]['children'] = [];
                    self_items = items[path_end[i]].children;
                    self_result = result[i]['children'];
                };
    
            }else{
                if(i !== path_end.length-1){
                    //not to the end
                    self_result[0] = {};
                    self_result[0]['name'] = self_items[path_end[i]].name;
                    self_result[0]['id'] = self_items[path_end[i]].id;
                    self_result[0]['children'] = [];
                    self_items = self_items[path_end[i]].children;
                    self_result = self_result[0]['children'];
                }else{
                    //to the end, check for the children end
                    self_result[0] = {};
                    self_result[0]['name'] = self_items[path_end[i]].name;
                    self_result[0]['id'] = self_items[path_end[i]].id;
                    if(self_items[path_end[i]].children){
                        self_result[0]['chidren'] = self_items[path_end[i]].children;
                    };
                    //check again the searching, if not match the name_to_search, set result to empty!
                    if(self_result[0]['name'] !== name_to_search){
                        result = [];
                    }
                };
    
            }
        };
        
    }else{
        result = [];
    }
    
    console.log(result);

    【讨论】:

      【解决方案2】:

      以下解决方案使用object-scan

      注意:(1) 输入未发生变异(2) 应为array -&gt; children 形式的良好输入。

      // const objectScan = require('object-scan');
      
      const finder = (name, input) => objectScan(['**(^children$).name'], {
        abort: true,
        useArraySelector: false,
        filterFn: ({ key, value, context, parents }) => {
          if (value !== name) {
            return false;
          }
          let cur = context;
          for (let idx = 0; idx < key.length - 1; idx += 1) {
            const segment = key[idx];
            if (idx % 2 === 0) {
              cur.push({ ...parents[parents.length - 1 - idx][segment] });
              cur = cur[0];
            } else {
              cur[segment] = [];
              cur = cur[segment];
            }
          }
          return true;
        }
      })(input, []);
      
      const items = [{ name: 'a1', id: 1, children: [{ name: 'a2', id: 2, children: [{ name: 'a3', id: 3 }] }, { name: 'b2', id: 5, children: [{ name: 'a4', id: 4 }] }] }];
      console.log(finder('a2', items));
      // => [ { name: 'a1', id: 1, children: [ { name: 'a2', id: 2, children: [ { name: 'a3', id: 3 } ] } ] } ]
      .as-console-wrapper {max-height: 100% !important; top: 0}
      &lt;script src="https://bundle.run/object-scan@13.8.0"&gt;&lt;/script&gt;

      免责声明:我是object-scan的作者

      【讨论】:

        猜你喜欢
        • 2023-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-03
        • 1970-01-01
        • 1970-01-01
        • 2013-12-22
        • 1970-01-01
        相关资源
        最近更新 更多