Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javascript从平面json数组(数据结构)构建类别树_Javascript_Arrays_Json_Recursion_Data Structures - Fatal编程技术网

javascript从平面json数组(数据结构)构建类别树

javascript从平面json数组(数据结构)构建类别树,javascript,arrays,json,recursion,data-structures,Javascript,Arrays,Json,Recursion,Data Structures,我试图使用javascript动态转换给定的平面JSON数组,以构建类别树。 但我不确定如何以最佳方式解决这个问题,从而使解决方案具有可扩展性。类别树需要从“/”分隔的“name”属性派生。 这是我的初步尝试 let data = [{"name":"file1.txt"},{"name":"folderA/file2.txt"},{"name":"folderA/folderB/fil

我试图使用javascript动态转换给定的平面JSON数组,以构建类别树。 但我不确定如何以最佳方式解决这个问题,从而使解决方案具有可扩展性。类别树需要从“/”分隔的“name”属性派生。 这是我的初步尝试

let data = [{"name":"file1.txt"},{"name":"folderA/file2.txt"},{"name":"folderA/folderB/file3.txt"},{"name":"file4.txt"}];
let tree = [];
function buildTree(data){
    data.forEach(obj => {
    let fileNameArr = obj.name.split("/");
    if(fileNameArr.length > 1){
     // Not sure
      }
    } else {
        let node = obj;
        node.type = "file";
        tree.push(node)
    }
  })
}

console.log(buildTree(data));
预期产出为:

[{"name":"file1.txt",
  "type":"file"
  },
 {
  "name":"folderA",
  "type":"Folder",
  "children":[
    {"name":"file2.txt",
     "type":"file"
    },
    {"name":"folderB",
     "type":"folder",
     "children":[{"name":"file3.txt","type":"file"}]
    }]
  },
 {"name":"file4.txt",
   "type":"file"
  }
]

要做到这一点,我发现做两个转换比较容易。第一种方法将上述内容转换为此结构:

{
“file1.txt”:{
“名称”:“file1.txt”,
“类型”:“文件”,
“儿童”:{}
},
“福尔德拉”:{
“姓名”:“福尔德拉”,
“类型”:“文件夹”,
“儿童”:{
“file2.txt”:{
“名称”:“file2.txt”,
“类型”:“文件”,
“儿童”:{}
},
“folderB”:{
“名称”:“folderB”,
“类型”:“文件夹”,
“儿童”:{
“file3.txt”:{
“名称”:“file3.txt”,
“类型”:“文件”,
“儿童”:{}
}
}
}
}
},
“file4.txt”:{
“名称”:“file4.txt”,
“类型”:“文件”,
“儿童”:{}
}
}
第二种方法是将其扁平化为一个数组,递归地对子对象执行同样的操作。我的做法如下:

//实用函数
常量调用=(fn,…args)=>
fn(…args)
//主要功能
常量嵌套=(文件)=>files.reduce((树,文件)=>{
file.name.split('/').reduce((节点,名称,i,a)=>{
返回(节点[名称]| |(节点[名称]={
名称
类型:i==a.length-1?'file':'folder',
儿童:{}
})).儿童
},树)
回归树
}, {})
const flattchildren=(树)=>
对象值(树)
.map(({children,…rest})=>调用(
(儿童)=>({
休息
…(kids.length?{children:kids}:{})
}),
儿童?儿童(儿童):[]
))
//公共职能
const makeTree=(文件)=>
展开子对象(嵌套(文件))
//样本输入
常量输入=[{name:'file1.txt'},{name:'folderA/file2.txt'},{name:'folderA/folderB/file3.txt'},{name:'file4.txt'}]
//演示
console.log(makeTree(输入))

.as console wrapper{max height:100%!important;top:0}
您可以通过查看实际级别并找到所需的名称来迭代数组并构建嵌套文件夹strruture。如果找不到,请添加新对象并返回用于推送文件的子数组

const
data=[{name:“file1.txt”},{name:“folderA/file2.txt”},{name:“folderA/folderB/file3.txt”},{name:“file4.txt”},
tree=data.reduce((r,{name})=>{
常数
folders=name.split(“/”),
file=folders.pop();
文件夹
.reduce((级别、名称)=>{
让temp=level.find(q=>q.name==name);
if(!temp)level.push(temp={name,键入:'folder',子项:[]});
返回临时儿童;
},r)
.push({name:file,键入:'file'});
返回r;
}, []);
控制台日志(树)

.as console wrapper{max height:100%!important;top:0;}
将整个数组简化为一个映射,并使用
初始化(基本数组)。无论何时创建文件夹,都可以使用其路径作为键将其添加到地图中,同时也可以将其添加到当前文件夹中

获取/添加最后一个文件夹(存储在
current
中)后,将文件添加到current

整个树存储在地图的
键中

const data=[{name:“file1.txt”},{name:“folderA/file2.txt”},{name:“folderA/folderB/file3.txt”},{name:“file4.txt”};
const createFile=name=>({name,类型:'file'});
const createFolder=name=>({name,类型:'folder',子项:[]});
const tree=data.reduce((acc,{name})=>{
const path=name.split(“/”);//获取路径
const file=createFile(path.pop());//创建文件
让current=acc.get('root');//在根上初始化current
//迭代current以访问最后一个文件夹,同时创建缺少的级别
path.forEach((folderName,i)=>{
const key=path.slice(0,i+1).join(“/”);//为当前文件夹创建密钥
如果(!acc.has(key)){//如果文件夹不是映射的一部分,请创建它
const folder=createFolder(folderName);
acc.set(键,文件夹);//将文件夹添加到地图
(current.children | | current).push(folder)//将文件夹添加到当前子文件夹/根目录
}
current=acc.get(key);//将current移动到文件夹
});
(current.children | | current).push(file)//将文件添加到当前子级/root
返回acc;
},新映射(['root',[]])//使用根文件夹初始化映射
.get('root');//把树从根上取下来
控制台日志(树)
。作为控制台包装{最大高度:100%!重要;顶部:0;}