根据 prop 值过滤深度嵌套数组并返回 Record 字符串

Filter deep nested array based on prop value and return a Record string

提问人:robb 提问时间:10/9/2023 更新时间:10/9/2023 访问量:45

问:

我有一个嵌套深度未知的对象数组(可以是 5 个甚至更多),如下所示:

const routes: routeType[] = [
{
  path: '/user', visible: true, title: 'User'
},
{
  path: "/admin", visible: true, title: "Admin", children: [
    {index: true, visible: false},
    {path: "dashboard", visible: true, title: "Dashboard"},
    {path: "changelog", visible: true, title: "Changelog"},
    {path: "profile", visible: true, title: "Profile"},
    {path: "settings", visible: true, title: "Settings", children: [
        {index: true, visible: false},
        {path: "themes", visible: true, title: "Theme"}
        {path: "themes/new", visible: true, title: "New"}
      ]
    }
  ]
}]

我想得到的结果是以这种方式组成的字符串记录:

const resultMap: Record<string, string> = {
"/admin": "Admin",
"/admin/dashboard": "Dashboard",
"/admin/changelog": "Changelog",
"/admin/profile": "Profile",
"/admin/settings": "Settings",
"/admin/settings/themes": "Themes",
"/admin/settings/themes/new": "New"}

所以:

  1. 使用“true”可见道具过滤所有记录。
  2. 构建由路径和标题组成的字符串记录(每个子路径都有对应的父路径)。

有很多类似的问题,但没有一个符合我的需求。我挣扎了两天,但最终还是找不到解决办法。你可以帮我吗?

提前致谢!

JavaScript 数组 TypeScript 对象 嵌套

评论


答:

0赞 Ale_Bianco 10/9/2023 #1

您可以尝试以递归方式处理 routes 数组并构建结果映射。

type Route = { path: string; visible: boolean; title: string; children?: Route[] };

const routes: Route[] = [
  // ... your routes here ...
];

function buildResultMap(routes: Route[], parentPath = ""): Record<string, string> {
  const resultMap: Record<string, string> = {};

  for (const route of routes) {
    const fullPath = `${parentPath}/${route.path}`.replace(/\/{2,}/g, '/'); // Remove double slashes if any
    if (route.visible) {
      resultMap[fullPath] = route.title;
    }
    if (route.children) {
      const childResult = buildResultMap(route.children, fullPath);
      Object.assign(resultMap, childResult);
    }
  }

  return resultMap;
}

const resultMap = buildResultMap(routes);

console.log(resultMap);
1赞 Behemoth 10/9/2023 #2

一个简单的递归函数是你的朋友。只需添加正确的类型注释,您就可以开始了。

function buildStringRecord(
  routes: RouteType[],
  parentPath: string = '',
  resultMap: Record<string, string> = {}
): Record<string, string> {
  for (const route of routes) {
    if (route.visible) {
      const fullPath = parentPath + route.path;
      if(route.title) {
        resultMap[fullPath] = route.title;
      }

      if (route.children) {
         buildStringRecord(route.children, fullPath + '/', resultMap);
      } 
    }
  }

  return resultMap;
}

const resultMap = buildStringRecord(routes);

TypeScript 操场

工作示例:

const routes = [ { path: '/user', visible: true, title: 'User', }, { path: '/admin', visible: true, title: 'Admin', children: [ { index: true, visible: false }, { path: 'dashboard', visible: true, title: 'Dashboard' }, { path: 'changelog', visible: true, title: 'Changelog' }, { path: 'profile', visible: true, title: 'Profile' }, { path: 'settings', visible: true, title: 'Settings', children: [ { index: true, visible: false }, { path: 'themes', visible: true, title: 'Theme' }, { path: 'themes/new', visible: true, title: 'New' } ] } ] }];

function buildStringRecord(
  routes,
  parentPath = "",
  resultMap = {}
) {
  for (const route of routes) {
    if (route.visible) {
      const fullPath = parentPath + route.path;
      if(route.title) {
        resultMap[fullPath] = route.title;
      }

      if (route.children) {
        buildStringRecord(route.children, fullPath + '/', resultMap);
      } 
    }
  }

  return resultMap;
}

const resultMap = buildStringRecord(routes);
console.log(resultMap);