我需要一个javascript函数来将具有文件路径字符串的数组转换为对象,如下所示:
let files = [
"Folder/file.ext",
"Folder/file2.ext",
"Folder/file3.ext",
"Folder/nestedfolder/file.ext",
"Folder2/file1.ext",
"Folder2/file2.ext",
"file1.ext",
"file2.ext",
"file3.ext",
];
listToTree(files);
并且它应该输出带有对象的数组,如下所示:
[
{
text: "Folder",
children: [
{text: "file.ext"},
{text: "file1.ext"},
{text: "file2.ext"},
{text: "nestedfolder", children: [{text: "file.ext"}]},
]
},
{
text: "Folder2",
children: [
{text: "file1.ext"},
{text: "file2.ext"},
]
},
{text: "file1.ext"},
{text: "file2.ext"},
{text: "file3.ext"}
];
这是我正在使用的当前功能。但是还不在那里。
function listToTree(files) {
let filestmp = files.map(file => {
if (typeof file === "string") return file;
return file.path
});
let filesl = filestmp.map(fileee => fileToObject(fileee));
return filesl;
}
function fileToObject(filee) {
if (filee.includes("/")) {
// this is a folder
let count = filee.indexOf("/");
return {text: filee.substring(0, count), children: [fileToObject(filee.substring(count + 1))]}
} else {
// this is a file
return {text: filee}
}
}
export default listToTree
它输出:
[ { text: 'Folder', children: [ { text: 'file.ext' } ] },
{ text: 'Folder', children: [ { text: 'file2.ext' } ] },
{ text: 'Folder', children: [ { text: 'file3.ext' } ] },
{ text: 'Folder',
children:
[ { text: 'nestedfolder', children: [ { text: 'file.ext' } ] } ] },
{ text: 'Folder2', children: [ { text: 'file1.ext' } ] },
{ text: 'Folder2', children: [ { text: 'file2.ext' } ] },
{ text: 'file1.ext' },
{ text: 'file2.ext' },
{ text: 'file3.ext' } ]
现在您可以看到。每个文件列表数组都有自己的对象。我需要合并位于同一文件夹位置的文件。
答案 0 :(得分:1)
以树表示为数组有点不方便,因为您需要每次搜索数组以找到合适的节点,这对于大型数组而言效率不高。 On选项是仅通过一次构建树对象,然后进行第二次通过以仅使用Object.values
。这是一个例子:
let files = ["Folder/file.ext","Folder/file2.ext","Folder/file3.ext","Folder/nestedfolder/file.ext","Folder2/file1.ext","Folder2/file2.ext","file1.ext","file2.ext","file3.ext",];
function addPath(arr, obj = {}){
let component = arr.shift()
let current = obj[component] || (obj[component] = {text:component})
if (arr.length) {
addPath(arr, current.children || (current.children = {}))
}
return obj
}
function makeArray(obj){
let arr = Object.values(obj)
arr.filter(item => item.children).forEach(item => {
item.children = makeArray(item.children)
})
return arr
}
// make tree
let treeObj = files.reduce((obj, path) => addPath(path.split('/'), obj), {})
// convert to array
let arr = makeArray(treeObj)
console.log(arr)
一种替代方法是使用find()
,它可以工作并且更易于阅读……但效率可能较低,因为您需要在每次通过时搜索结果数组:
let files = ["Folder/file.ext","Folder/file2.ext","Folder/file3.ext","Folder/nestedfolder/file.ext","Folder2/file1.ext","Folder2/file2.ext","file1.ext","file2.ext","file3.ext",];
function addPath(pathcomponents, arr ){
let component = pathcomponents.shift()
let comp = arr.find(item => item.text === component)
if (!comp) {
comp = {text: component}
arr.push(comp)
}
if(pathcomponents.length){
addPath(pathcomponents, comp.children || (comp.children = []))
}
return arr
}
let res = files.reduce((arr, path) => addPath(path.split('/'), arr), [])
console.log(res)
答案 1 :(得分:1)
这是我的观点,一个功能,没有递归:
const listToTree = files =>
files.map(file => file.split('/'))
.reduce((out, path) => {
let top = out;
while (path.length > 0) {
let node = path.shift();
if (top.findIndex(n => n.text === node) === -1) {
top.push({
text: node
});
}
if (path.length > 0) {
let index = top.findIndex(n => n.text === node);
top[index] = top[index] || {};
top[index].children = top[index].children || [];
top[index].children.push({
text: path[0]
});
top = top[index].children;
}
}
return out;
}, []);
let files = [
'Folder/file.ext',
'Folder/file2.ext',
'Folder/file3.ext',
'Folder/nestedfolder/file.ext',
'Folder2/nestedfolder1/nestedfolder2/file1.ext',
'Folder2/file2.ext',
'file1.ext',
'file2.ext',
'file3.ext'
];
console.log(listToTree(files));