Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert array of arrays into deep nested tree view

I'm building a tree view by converting array of paths into tree view data structure. Here's what I want to do:

// routes are sorted.
let routes = [
    ['top', '1.jpg'],
    ['top', '2.jpg'],
    ['top', 'unsplash', 'photo.jpg'],
    ['top', 'unsplash', 'photo2.jpg'],
    ['top', 'foo', '2.jpg'],
    ['top', 'foo', 'bar', '1.jpg'],
    ['top', 'foo', 'bar', '2.jpg']
];

into 

let treeview = {
  name: 'top', child: [
    {name: '1.jpg', child: []},
    {name: '2.jpg', child: []},
    {name: 'unsplash', child: [
        {name: 'photo.jpg', child: []},
        {name: 'photo2.jpg', child: []}
    ]},
    {name: 'foo', child: [
        {name: '2.jpg', child: []},
        {name: 'bar', child: [
            {name: '1.jpg', child: []},
            {name: '2.jpg', child: []}
        ]}
    ]}
]}

Now I've successfully convert single array of items via this method, but unable to do so for multiple array. Note also, nested treeview doesn't contain duplicate.

function nest(arr) {
    let out = [];
    arr.map(it => {
        if(out.length === 0) out = {name: it, child: []}
        else {
            out = {name: it, child: [out]}
        }
    });
    return out;
}
like image 799
Ashish Rawat Avatar asked Jan 26 '18 18:01

Ashish Rawat


1 Answers

You could use a nested hash table for the access for the routes and take an array as result set. If you have only one root element, you could take the first element of the result array.

var routes = [['top', '1.jpg'], ['top', '2.jpg'], ['top', 'unsplash', 'photo.jpg'], ['top', 'unsplash', 'photo2.jpg'], ['top', 'foo', '2.jpg'], ['top', 'foo', 'bar', '1.jpg'], ['top', 'foo', 'bar', '2.jpg']],
    result = [],
    temp = { _: result };

routes.forEach(function (path) {
    path.reduce(function (level, key) {
        if (!level[key]) {
            level[key] = { _: [] };
            level._.push({ name: key, children: level[key]._ });
        }
        return level[key];
    }, temp);
});

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

ES6 without a temporary object, but with a seach of a named object with the path name.

var routes = [['top', '1.jpg'], ['top', '2.jpg'], ['top', 'unsplash', 'photo.jpg'], ['top', 'unsplash', 'photo2.jpg'], ['top', 'foo', '2.jpg'], ['top', 'foo', 'bar', '1.jpg'], ['top', 'foo', 'bar', '2.jpg']],
    result = [];

routes.forEach(function (path) {
    path.reduce(function (level, key) {
        var temp = level.find(({ name }) => key === name);
        if (!temp) {
            temp = { name: key, children: [] };
            level.push(temp);
        }
        return temp.children;
    }, result);
});

console.log(result);    
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 76
Nina Scholz Avatar answered Oct 17 '22 02:10

Nina Scholz