Nested tree Structure Data Generation

余生长醉 提交于 2020-01-06 07:13:29

问题


please bare with my English and writing question, i have a array of json data which i am trying to make it in a nested tree structure but not getting success , hope someone can help me out. My Example Data:

[ {
  "id" : 1,
  "name" : "Abc",
  "path" : "/",
  "type" : "folder"
}, {
  "id" : 2,
  "name" : "Xyz",
  "path" : "/Abc/",
  "type" : "folder"
}, {
  "id" : 3,
  "name" : "Pqr",
  "path" : "/Abc/Xyz/",
  "type" : "folder"
}, {
  "id" : 4,
  "name" : "Zap", 
  "path" : "/Abc/Xyz/Pqr/",
  "type" : "folder"
 },{
  "id" : 5,
  "name" : "file1", 
  "path" : "/Abc/Xyz/Pqr/",
  "type" : "file"
},{
  "id" : 6,
  "name" : "file2", 
  "path" : "/Abc/Xyz/Pqr/",
  "type" : "file"
},{
  "id" : 7,
  "name" : "file3", 
  "path" : "/Abc/Xyz/",
  "type" : "file"
},{
  "id" : 8,
  "name" : "file4", 
  "path" : "/Abc/Xyz/Pqr/Zap/",
  "type" : "file"
}

Sorry i am taking little big data to make understand properly, now the nested format i which i want it is something like this.

[{
  "id" : 1,
  "name" : "Abc",
  "path" : "/",
  "type" : "folder"
  "Children":[{
    "id" : 2,
    "name" : "Xyz",
    "path" : "/Abc/",
    "type" : "folder",
    "Children":[{
           "id" : 3,
           "name" : "Pqr",
           "path" : "/Abc/Xyz/",
           "type" : "folder",
           "Children": [{
                   "id" : 4,
                    "name" : "Zap", 
                    "path" : "/Abc/Xyz/Pqr/",
                    "type" : "folder",
                    "Children":[{
                            "id" : 8,
                             "name" : "file4", 
                              "path" : "/Abc/Xyz/Pqr/Zap/",
                             "type" : "file"
                         }]
                   },{
                    "id" : 5,
                    "name" : "file1", 
                    "path" : "/Abc/Xyz/Pqr/",
                    "type" : "file"
                   },{
                      "id" : 6,
                      "name" : "file2", 
                      "path" : "/Abc/Xyz/Pqr/",
                      "type" : "file"
             }]
         },{
           "id" : 7,
           "name" : "file3", 
           "path" : "/Abc/Xyz/", 
           "type" : "file"
      }]
 }]
 }

Now the login using with lodash is like this: datas = allData

 const dd= [];
_.forEach(datas, function(v, k) {
  let cc = {};
    if (v.type == 'folder') {

      cc['children'] = _.filter(datas, function(v1, k1) {
        if (v.path + v.name + '/' == v1.path || v1.path.startsWith(v.path + v.name + '/')) {
          return v1;
        }
      });
      cc['name'] = v.name;
      cc['type'] = v.type;
      cc['id'] = v.id;
      cc['path'] = v.path;
      dd.push(cc);
    } else {
      if (v.path == '/') {
        dd.push(cc);
      }
    }

});

But not getting it properly, i know question got too long but help me out with this.


回答1:


Whew! That was fun.

const data = [ {
  "id" : 1,
  "name" : "Abc",
  "path" : "/",
  "type" : "folder"
}, {
  "id" : 2,
  "name" : "Xyz",
  "path" : "/Abc/",
  "type" : "folder"
}, {
  "id" : 3,
  "name" : "Pqr",
  "path" : "/Abc/Xyz/",
  "type" : "folder"
}, {
  "id" : 4,
  "name" : "Zap", 
  "path" : "/Abc/Xyz/Pqr/",
  "type" : "folder"
 },{
  "id" : 5,
  "name" : "file1", 
  "path" : "/Abc/Xyz/Pqr/",
  "type" : "file"
},{
  "id" : 6,
  "name" : "file2", 
  "path" : "/Abc/Xyz/Pqr/",
  "type" : "file"
},{
  "id" : 7,
  "name" : "file3", 
  "path" : "/Abc/Xyz/",
  "type" : "file"
},{
  "id" : 8,
  "name" : "file4", 
  "path" : "/Abc/Xyz/Pqr/Zap/",
  "type" : "file"
}]

const pathPartRegex = /.*?\//g;
const tree = _.reduce(data, (result, value) => {
    const pathParts = value.path.match(pathPartRegex);
    let node = result;
    let path = "";

    // Go down through tree until last path part
    const notLastPart = pathParts.splice(0, pathParts.length - 1);
    for (const pathPart of notLastPart) {
        path += pathPart;
        const existingNode = node.children 
                                ? node.children.find(item => item.path === path)
                                : node.find(item => item.path === path);
        if (existingNode) {
            node = existingNode
        } else {
            // If we need to traverse over a path that doesn't exist, just create it
            // See notes 
            const newNode = {
                path: path,
                children: []
            };

            // The root element is just an array, and doesn't have a children property
            if (node.children) {
                node.children.push(newNode);
            } else {
                node.push(newNode);
            }
            node = newNode;
        }
    }

    // Add new node
    const newNode = {
        id: value.id,
        name: value.name,
        type: value.type,
        path: value.path,
        children: []
    };

    // The root element is just an array, and doesn't have a children property
    if (node.children) {
        node.children.push(newNode);
    } else {
        node.push(newNode);
    }

    return result;
}, []);

Tested via RunKit (https://npm.runkit.com/lodash)


Notes:

The sample data set does not cover how to handle a situation where the "parent" path is not defined at all:

const data = [{
  "id" : 1,
  "name" : "Abc",
  "path" : "/",
  "type" : "folder"
}, {
  "id" : 3,
  "name" : "Pqr",
  "path" : "/Abc/Xyz/",
  "type" : "folder"
}];

Nor a situation where the "parent" path is defined after the child:

const data = [{
  "id" : 1,
  "name" : "Abc",
  "path" : "/",
  "type" : "folder"
}, {
  "id" : 3,
  "name" : "Pqr",
  "path" : "/Abc/Xyz/",
  "type" : "folder"
}, {
  "id" : 2,
  "name" : "Xyz",
  "path" : "/Abc/",
  "type" : "folder"
}];

The code I wrote will handle these, but may create nodes without an id property. If you need to handle situations like that, you can either fix the input data beforehand or modify this code to handle those situations.




回答2:


The answer which i also got working is something like this:

const sts=_.memoize(function(){ return []; });
const result = _.filter(folderdata, function(item){
  let parentName = '';
  if(item.path != '/')parentName = item.path;
  item.children = sts(item.path+item.name+'/');
  if (item.type == 'folder') return !(parentName && sts(parentName).push(item));
});


来源:https://stackoverflow.com/questions/52779517/nested-tree-structure-data-generation

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