2

I get a list of file paths from the backend, it represents a folder structure and looks like this:

paths = ["path/to/file1.doc", "path/to/file2.doc", "foo/bar.doc]

The lengths of the paths are arbitrary. In order to use a file tree component (angular2-tree-component) I need to transform this data into the following format:

nodes = [
    {
        "name": "path",
        "children": [
            {
                "name": "to",
                "children": [
                    {"name": "file1.doc"},
                    {"name": "file2.doc"}
                ]
            }
        ]
    },
    {
        "name": "foo",
        "children": [
            {"name": "bar.doc"}
        ]
    }
]

I think the most efficient way to transform the data is to

  1. Map the array with the files mirroring a tree structure first and then to
  2. Iterate over every key in order to finalise the "children/parent" relations.

Step one:

transformToTree(data) {
    const tree = {};
    function addPathsToTree(paths) {
        let map = tree
        paths.forEach(function(item) {
            map[item] = map[item] || {};
            map = map[item];
        });
    }
    data.forEach(function(path) {
        let pathPart = path.split('/');
        addPathsToTree(pathPart);
    });
    return pathTree;
}

When passing "nodes" into the transformToTree function (transformToTree(nodes)), I get the following result:

{
    "path": {
        "to": {
            "file1.doc": {},
            "file2.doc": {}
        }
    },
    "foo": {
        "bar": {}
    }
}

I don't know how to proceed from here = how to iterate over all the keys and values while building the final array in the required structure.

There are a few examples like this or that on SO, but I was not able to understand how I could adapt them to my needs.

1 Answer 1

8

I would go with two nested loops, one for pathes and one for the splitted names and find the name or create new objects.

var paths = ["path/to/file1.doc", "path/to/file2.doc", "foo/bar.doc"],
    result = [];
    
paths.reduce((r, path) => {
    path.split('/').reduce((o, name) => {
        var temp = (o.children = o.children || []).find(q => q.name === name);
        if (!temp) o.children.push(temp = { name });
        return temp;
    }, r);
    return r;
}, { children: result });

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

1 Comment

Smart. Thank you very much for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.