路由扁平化

491 阅读1分钟

一次面试因为递归漏写了 return 和对前缀置为空字符串导致结果始终不对,最后被面试官提前终止了面试。面试官一退出房间我就把代码改好了,这次面试给我留下的印象很深刻,所以记录下这个题目。

题目描述

有以下数据结构:

const testCase = [
  {
    path: '/jobs',
    routes: [
      {
        path: '/auto_create',
      },
      {
        path: '/:jobId',
        routes: [
          {
            path: '/info',
          },
          {
            path: '/setting',
          },
          {
            path: '/manager',
          },
          {
            path: '/source',
          },
          {
            path: '/smart_recruitment',
          },
          {
            path: '/satisfaction',
            routes: [
              {
                path: ['/pandect/:candidateId', '/application/:applicationId', '/:id'],
              },
            ],
          },
        ],
      },
    ],
  },
];

期望得到以下结果:

// 得到结果
// [
//   '/jobs/auto_create',
//   '/jobs/:jobId/info',
//   '/jobs/:jobId/setting',
//   '/jobs/:jobId/manager',
//   '/jobs/:jobId/source',
//   '/jobs/:jobId/smart_recruitment',
//   '/jobs/:jobId/satisfaction/pandect/:candidateId',
//   '/jobs/:jobId/satisfaction/application/:applicationId',
//   '/jobs/:jobId/satisfaction/:id',
// ];

解决

题目是要把嵌套的 path 都串起来组成一条路有,所以第一时间想到递归。

function flattenRoutes (testCase = []) {
  // todo
  var ret = []
  flatten(testCase, ret, '')
  return ret
}

function flatten (testCase = [], ret = [], prefix = '') {
  testCase.map(item => {
    if (item.routes) return flatten(item.routes, ret, prefix + item.path)

    if (Array.isArray(item.path)) {
      item.path.forEach(str => {
        const path = prefix.length ? prefix + str : str
        ret.push(path)
      })
    } else {
      const path = prefix.length ? prefix + item.path : item.path
      ret.push(path)
    }
  })
}

递归那里需要 return,否则还会执行后续代码,导致结果不对。除此之外前缀也不需要在遍历到底时赋值为空字符串,因为前缀始终需要保留前一层遍历时的前缀。