0

i've got the following array of objects

let prova: ActiveRoute[] = [
{
    path: '/Root',
    method: 'GET',
    children: [
        {
            path: '/Son',
            method: 'GET',
            children: [
                {
                    path: '/Grandson',
                    method: 'GET',
                    children: [
                        {
                            path: '/Boh',
                            method: 'GET',
                            activeMessage: 'End',
                        }
                    ],
                }
            ],
        }
    ],
    middleware: [
        'middleware1',
    ],
}

This is the ActiveRoute interface

export interface  ActiveRoute {
   path: string;
   children?: ActiveRoute[];
   middleware?: string[];
   method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
   activeMessage?: string;

}

I want to print all the path properties in a string. What should i do?

This is what i've done (wrong)

function getEndPoints(prova) {
let endpoints: string = '';
prova.forEach((r) => {
    if (r.path) {
        endpoints += r.path;
        if(r.children){
            r.children.forEach((s) => {
                if (s.path) {
                    endpoints += s.path;
                }
                if (s.children){
                    s.children.forEach((z) =>{
                        if (z.path){
                            endpoints += z.path;
                        }
                    });
                }
            });
        }
    }
});
console.log(endpoints);

}

I really don't understand how should i loop continuously and deeply within an array of objects. This is my desire output, in this case: '/Root/Son/Grandson/Boh'.

Obviously now i don't how i'll go deep within.

6
  • 3
    StackOverflow isn't here to do your work for you. Show us what you have tried so far. We'll gladly help you. Commented Feb 2, 2018 at 15:26
  • Sure, i forgot to add it Commented Feb 2, 2018 at 15:28
  • 2
    While you are adding things, add the desired output from the collection you've entered. Commented Feb 2, 2018 at 15:30
  • 2
    desire output: /Root/Son/Grandson/Boh What if you have multiple children on any of the levels?. Commented Feb 2, 2018 at 15:35
  • I corrected the post. Commented Feb 2, 2018 at 15:37

2 Answers 2

1

Your input structure could have multiple results,..

eg. below I've modified so that /Grandson has multiple children.

let prova = [
{
    path: '/Root',
    method: 'GET',
    children: [
        {
            path: '/Son',
            method: 'GET',
            children: [
                {
                    path: '/Grandson',
                    method: 'GET',
                    children: [
                        {
                            path: '/Boh',
                            method: 'GET',
                            activeMessage: 'End',
                        },
                        {
                            path: '/AnotherBoh',
                            method: 'GET',
                            activeMessage: 'End',
                        }
                    ],
                }
            ],
        }
    ],
    middleware: [
        'middleware1',
    ]
}];

function getLinks(p) {
  const arr = [];
  function inner(p, root) {
    p.forEach((x) => {
      const newroot = root + x.path;
      if (!x.children) {
        arr.push(newroot);
      } else {
        inner(x.children, newroot);
      }
    });
  }
  inner(p, "");
  return arr;
}

console.log(getLinks(prova));

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

2 Comments

Thank you for your answer, i didn't think about recursion
Recursion should leap to your mind when you see a structure like this. It's really the only technique that will do.
0

Here's another possibility, based on @Keith's answer, but which returns the list of paths as an array of strings rather than logging them.

let prova = [{
    path: '/Root',
    children: [{
        path: '/Son',
        children: [{
            path: '/Grandson',
            children: [{
                path: '/Boh',
            }, {
                path: '/AnotherBoh',
                children: [{
                   path: '/Foo'
                }, {
                  path: '/Bar'
                }]
            }]
        }]
    }, {
        path: '/AnotherSon',
    }],
    middleware: ['middleware1']
}];

function getPaths(p, base = "", gather = []) {
  return p.map((node) => {
    if (node.children) {
      getPaths(node.children, base + node.path, gather);
    } else {
      gather.push(base + node.path);
    }
    return gather
  }).reduce((a, b) => a.concat(b), []); // removes an (unnecessary?) level of nesting
}

console.log(getPaths(prova));

Note that I removed a number of irrelevant properties, but added nesting at several levels, just to test.


Update

Here's a cleaner version of the same idea:

const flat = arr => arr.reduce((out, item) => out.concat(item), [])

const getPaths = (p, base = "", gather = []) => flat(p.map((node) => ('children' in node) 
    ? getPaths(node.children, base + node.path, gather)
    : gather.concat(base + node.path)
))

2 Comments

but which returns the list of paths Good point, I've altered mine to return an array too, as in real life would be much more useful.
Yes, it looks as though ours our quite similar now. I think I like your inner function better than my gather parameter and final flattening step. But I definitely prefer a map to a forEach.

Your Answer

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