如上所述将带有文件路径的数组转到对象

时间:2018-10-31 15:27:25

标签: javascript node.js

我需要一个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' } ]

现在您可以看到。每个文件列表数组都有自己的对象。我需要合并位于同一文件夹位置的文件。

2 个答案:

答案 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));