Justin
Justin

Reputation: 972

Convert Array of Paths into Object Array groupings

I did find this question How to convert an array of paths into JSON structure? but, I can't seem to manipulate the answer to achieve what I want.

I have an array of Paths that I want to turn into an object that can be easily used on the client.

[
    "\\Folder\file.xlsx",
    "\\Folder\file2.xlsx",
    "\\Folder\file3.docx",
    "\\Folder\Folder2\file4.xlsx",
    "\\Folder\Folder2\Folder3\file5.xlsx",
    "\\Folder\Folder2\file6.xlsx",
    "\\Folder\Folder4\file7.pdf"
    "\\Folder\Folder4\Folder5\1. file8.pdf"
]

I'm trying to get an output that looks something like this:

output = {
    Folder: {
        {
            file: file.xlsx,
            path: \\Folder\file.xlsx

        }, 
        {
            file: file2.xlsx,
            path: \\Folder\file2.xlsx
        }, 
        {
            file: file3.xlsx,
            path: \\Folder\file3.docx
        }
        Folder2: {

                {
                    file: file4.xlsx,
                    path: \\Folder\Folder2\file4.xlsx
                }, 
                Folder3:{

                        {
                            file: file5.xlsx,
                            path: \\Folder\Folder2\Folder3\file5.xlsx
                        },

                },
                {
                    file: file6.docx,
                    path: \\Folder\Folder2\file6.xlsx
                } 
        },
        Folder4: {
            {
                file: file7.pdf,
                path: \\Folder\Folder4\file7.pdf
            },
            Folder5: {
                {
                    file: 1. file8.pdf,
                    path: \\Folder\Folder4\Folder5\1. file8.pdf
                },
            }
        }
    }
}

currently, I have this which gives me empty objects but no path:

        var output = {};
        var current;

        for (var a = 0; a < files.length; a++) {
            var s = files[a].split("\\");
            // console.log("s ===> ", s);
            current = output;

            for (var i = 0; i < s.length; i++) {
                if (s[i] != "") {
                    if (current[s[i]] == null) {
                        current[s[i]] = {};
                    } else {
                        current = current[s[i]];
                    }
                }
            }
        }

But it doesn't return quite what I am looking for. I'm not entirely sure if there are functions like map or reduce that can help with this as I'm quite new to Javascript.

If someone could point me in the right direction that would be great.

Upvotes: 1

Views: 99

Answers (2)

Hikmat G.
Hikmat G.

Reputation: 2621

This will work recursively so you can go deeper like \\Folder\\........\\Folder10\\file.doc;

const files = [
  "\\Folder\\file.xlsx",
  "\\Folder\\file2.xlsx",
  "\\Folder\\file3.docx",
  "\\Folder\\Folder2\\file4.xlsx",
  "\\Folder\\Folder2\\Folder3\\file5.xlsx",
  "\\Folder\\Folder2\\file6.xlsx",
  "\\Folder\\Folder4\\file7.pdf",
  "\\Folder\\Folder4\\Folder5\\1. file8.pdf"
];

const result = files.reduce((obj, p) => {

  let temp = obj;
  p.split('\\').forEach((d, i, arr) => {
    if (!d) return;
    if (i === 0) return;
    if (i === arr.length - 1) {
      temp['files'] = [...(temp['files'] || []), {
        file: d,
        path: p
      }];
    } else if (!temp[d]) {
      temp[d] = {};
    }
    temp = temp[d];
  });

  return obj;
}, {});

console.log(result);

Direct files of a folder are in files array.

{
  "Folder": {
    "files": [
      {
        "file": "file.xlsx",
        "path": "\\Folder\\file.xlsx"
      },
      {
        "file": "file2.xlsx",
        "path": "\\Folder\\file2.xlsx"
      },
      {
        "file": "file3.docx",
        "path": "\\Folder\\file3.docx"
      }
    ],
    "Folder2": {
      "files": [
        {
          "file": "file4.xlsx",
          "path": "\\Folder\\Folder2\\file4.xlsx"
        },
        {
          "file": "file6.xlsx",
          "path": "\\Folder\\Folder2\\file6.xlsx"
        }
      ],
      "Folder3": {
        "files": [
          {
            "file": "file5.xlsx",
            "path": "\\Folder\\Folder2\\Folder3\\file5.xlsx"
          }
        ]
      }
    },
    "Folder4": {
      "files": [
        {
          "file": "file7.pdf",
          "path": "\\Folder\\Folder4\\file7.pdf"
        }
      ],
      "Folder5": {
        "files": [
          {
            "file": "1. file8.pdf",
            "path": "\\Folder\\Folder4\\Folder5\\1. file8.pdf"
          }
        ]
      }
    }
  }
}

Upvotes: 1

sjahan
sjahan

Reputation: 5960

Here is an example with map and reduce :)

Watch out, your expected output is not valid, so i've adjusted a bit to what seems the most natural.

const files = [
    "\\Folder\\file.xlsx",
    "\\Folder\\file2.xlsx",
    "\\Folder\\file3.docx",
    "\\Folder\\Folder2.xlsx",
    "\\Folder\\Folder2\\file4.xlsx",
    "\\Folder\\Folder3\\file5.xlsx",
    "\\Folder\\Folder3\\file6.docx",
    "\\Folder\\Folder4\\file7.pdf"
];

const result = files.map(filePath => 
({
  path: filePath, 
  file: filePath.substring(filePath.lastIndexOf('\\')+1)
})).reduce((acc, item) => {
  const folderPath = item.path.substring(0, item.path.length-(item.file.length+1));
  const folder = folderPath.substring(folderPath.lastIndexOf('\\')+1);
  acc[folder] = acc[folder] || [];
  acc[folder].push(item);
  return acc;
}, {});

console.log(result);

Here is a small explanation:

First, you map your files to the expected objects, then, you re-organize them with reduce! You pipe both map and reduce and it is doing the job!

Upvotes: 3

Related Questions