嵌套树结构数据生成

时间:2018-10-12 12:25:03

标签: javascript angular loops lodash angular6

请问一下我的英语和写作问题,我有一组json数据,我试图将其制成嵌套树状结构,但未获得成功,希望有人能帮助我。 我的示例数据:

[ {
  "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"
}

抱歉,我需要少量的大数据才能正确理解,现在我想要的嵌套格式就是这样。

[{
  "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"
      }]
 }]
 }

现在与lodash一起使用的登录如下: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);
      }
    }

});

但是得不到正确的答案,我知道问题已经太久了,但是请帮我解决这个问题。

2 个答案:

答案 0 :(得分:2)

哇!很好玩。

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;
}, []);

通过RunKit(https://npm.runkit.com/lodash)进行了测试


注意:

样本数据集没有涵盖如何处理根本没有定义“父”路径的情况:

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

在子级之后也没有定义“父级”路径的情况:

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"
}];

我编写的代码将处理这些问题,但可能会创建没有id属性的节点。如果需要处理这种情况,则可以预先修复输入数据,也可以修改此代码以处理这些情况。

答案 1 :(得分:0)

我也正在努力的答案是这样的:

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));
});