I have an object of nested route.
Any route MAY contains a list of route childRoutes
.
I want to get the list of all the route that contains the key menu
.
const routes = [{
"name": "userManagement",
"childRoutes": [
{
"name": "blogManagement",
"childRoutes": [
{
"name": "blog", // <=== I want to have this route
"menu": {
"role": 1020
}
}
],
},
{
"name": "organizationList", // <=== and this one
"menu": {
"role": 1004
}
}
],
}, {
"name": "test",
"menu": { "role": 4667 }
}];
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
// Should handle nesting of route
const links = deepFlatten(routes).filter((r) => !!r.menu);
console.log('it should have a length of 3:', links.length === 3);
console.log('it should be blog:', links[0].name === 'blog');
console.log('it should be organizationList:', links[1].name === 'organizationList');
console.log('it should be test:', links[2].name === 'test');
I have an object of nested route.
Any route MAY contains a list of route childRoutes
.
I want to get the list of all the route that contains the key menu
.
const routes = [{
"name": "userManagement",
"childRoutes": [
{
"name": "blogManagement",
"childRoutes": [
{
"name": "blog", // <=== I want to have this route
"menu": {
"role": 1020
}
}
],
},
{
"name": "organizationList", // <=== and this one
"menu": {
"role": 1004
}
}
],
}, {
"name": "test",
"menu": { "role": 4667 }
}];
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
// Should handle nesting of route
const links = deepFlatten(routes).filter((r) => !!r.menu);
console.log('it should have a length of 3:', links.length === 3);
console.log('it should be blog:', links[0].name === 'blog');
console.log('it should be organizationList:', links[1].name === 'organizationList');
console.log('it should be test:', links[2].name === 'test');
The above snippet does not work recursively yet.
How can I do it recursively without any third-party library ?
Share Improve this question edited Jan 9, 2018 at 16:43 Dimitri Kopriwa asked Jan 9, 2018 at 15:45 Dimitri KopriwaDimitri Kopriwa 14.4k32 gold badges112 silver badges231 bronze badges 9- Can a node contain both a menu key and a childnodes key? – Glubus Commented Jan 9, 2018 at 15:48
- @Glubus is there a reason not to assume it's possible? – Reinstate Monica Cellio Commented Jan 9, 2018 at 15:51
-
Well the algorithm needs to take this into account. If you look at zfrisch' answer, you see that his algorithm terminates whenever it finds
menu
. If both keys are allowed to exist within the same node, you need to traverse the rest of the tree and see if the rest of the nodes along the route are also part of your result. – Glubus Commented Jan 9, 2018 at 15:56 - Yes, there's a reason to accept the possibility. So, back to my original question, is there a reason not to assume it's possible? – Reinstate Monica Cellio Commented Jan 9, 2018 at 15:58
-
1
@BigDong okay, I'll update my answer, but this is a question I asked you before you deleted and reposted and you said that all
menu
items were found inside child routes. – zfrisch Commented Jan 9, 2018 at 16:05
2 Answers
Reset to default 8@yBrodsky's answer can be adapted to isolate and exhibit the generic flatMap
operation – here, you'll see that the routes flattened with much of the reduce
-map
-concat
plumbing out of the programmer's way.
// polyfill if you don't have it
Array.prototype.flatMap = function (f)
{
return this.reduce ((acc, x) =>
acc.concat (f (x)), [])
}
// your data
const routes =
[ { name : "userManagement"
, childRoutes :
[ { name : "blogManagement"
, childRoutes :
[ { name : "blog"
, menu : { role : 1020 }
}
]
}
, { name : "organizationList"
, menu : { role : 1004 }
}
]
}
, { name : "test"
, menu : { role : 4667 }
}
]
// flat-mapped routes
const allChildRoutes =
routes.flatMap (function loop (node) {
if (node.childRoutes)
return node.childRoutes.flatMap (loop)
else
return [node]
})
console.log (allChildRoutes)
how about this, seems to work.
const flatten = (routes) => {
return routes.reduce((acc, r) => {
if(r.childRoutes && r.childRoutes.length) {
acc = acc.concat(flatten(r.childRoutes));
} else {
acc.push(r);
}
return acc;
}, [])
}
https://jsfiddle/vv9odcxw/