Javascript 嵌套树结构数据生成
请直接回答我的英语和写作问题,我有一个json数据数组,我正试图将它做成嵌套的树结构,但没有成功,希望有人能帮助我。 我的示例数据:Javascript 嵌套树结构数据生成,javascript,angular,loops,lodash,angular6,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", "
[ {
"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);
}
}
});
但并没有得到正确的答案,我知道问题太长了,但请帮我解决这个问题。哇!那很有趣
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()进行测试
注: 示例数据集不包括如何处理根本未定义“父”路径的情况:
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
属性的节点。如果您需要处理这样的情况,您可以事先修复输入数据,也可以修改此代码来处理这些情况。哇!那很有趣
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()进行测试
注: 示例数据集不包括如何处理根本未定义“父”路径的情况:
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
属性的节点。如果您需要处理这样的情况,您可以事先修复输入数据,也可以修改此代码来处理这些情况。我也得到了如下答案:
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));
});
我得到的答案是这样的:
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));
});
这是一致的,你知道吗?它总是有id、路径、名称、类型和子项,如果有一致的内容,知道吗?它总是有id、路径、名称、类型和子项,如果有什么真的很好的答案,最后只有一个问题您返回结果,但您没有为结果分配任何内容,除了每次更新的方式?我还在下面分享了一个解决方案。@user3458271本质上,这就是reduce的工作原理。它以空数组的初始值开始(第三个参数)每次迭代返回的值都会传递给nextyo,这真是一个很好的答案。最后只回答了一个问题。您返回的是结果,但您没有为结果分配任何内容,只是每次更新的方式。下面我还分享了一个解决方案。@user3458271本质上,这就是reduce的工作方式。它以一个空数组的初始值(第三个参数)开始,并将每次迭代返回的值传递给下一个数组