最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

recursion - How to write a recursive flat map in javascript? - Stack Overflow

programmeradmin4浏览0评论

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
 |  Show 4 more ments

2 Answers 2

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/

发布评论

评论列表(0)

  1. 暂无评论