将字符串转换为嵌套的 objects 和数组

Convert string into nested objects and arrays

我在一个项目中,前一个人做了一些奇怪的路由,基本上我以字符串的形式从 contentful 中获取了 slug,我将其放入数组中 ["/api/", "/docs/getting-started/", "/docs/, "/plugin/", "/plugin/user/", "/plugin/profile/"......]

现在需要转换成数组的形式

let cleanedSidebarContents = [{
              title:null,
              pages:[
                     {title:"api",
                      path:"/api/"
                      },
                     {title:"docs",
                      path:"/docs/"
                      },
                      {title:"plugin",
                      path:"/plugin/"
                      },
                     ]
               },
             {
              title:"plugin",
              pages:[
                     {title:"user",
                      path:"/plugin/user/"
                      },
                     {title:"profile",
                      path:"/plugin/profile/"
                      },
                     ]
               },
              {
              title:"docs",
              pages:[
                     {title:"getting-started",
                      path:"/plugin/getting-started/"
                      },
                     ]
               }
]

所以目前我正在做的是这个-

 //-------Format sidebar data--------------->
    let cleanedSidebarContents = [];
    (function cleanSidebarContents() {

        let sideBarContentsContentful = [];
        cleanContentfulEdges.forEach(edge => {
            let slug = edge.node.slug;
            //split string into titles and remove empty spaces
            let routeMapArray = slug.split("/").filter(x => x != "");
            if (routeMapArray.length > 1) {
                sideBarContentsContentful.push({
                    title: routeMapArray[0],
                    page: {
                        title: routeMapArray[routeMapArray.length - 1],
                        path: edge.node.slug
                    }
                });
            } else {
                sideBarContentsContentful.push({
                    title: null,
                    page: {
                        title: routeMapArray[routeMapArray.length - 1],
                        path: edge.node.slug
                    }
                });
            }
        });

        let titles = [];
        for (let i = 0; i < sideBarContentsContentful.length; i++) {
            titles.push(sideBarContentsContentful[i].title);
        }
        //clean duplicate entries
        titles = titles.filter(function (item, index, inputArray) {
            return inputArray.indexOf(item) === index;
        });
        titles.sort();

        titles.map(item => {
            cleanedSidebarContents.push({
                title: item,
                pages: []
            })
        });

        sideBarContentsContentful.forEach(item => {
            for (let i = 0; i < cleanedSidebarContents.length; i++) {
                if(cleanedSidebarContents[i].title === item.title){
                    cleanedSidebarContents[i].pages.push(item.page)
                }
            }
        });
    }());
    //----------------------------------------->

我首先拆分所有字符串并将标题放入标题数组,然后删除重复项并相应地映射数据。

我只是觉得这是非常糟糕的代码,还有更好的方法我只是想不出来。

您可以创建一个 mapper 对象,它将输出中的对象映射到每个对象根中的 titlesplit/ 获取所有路径块。 .filter(Boolean) 删除从字符串开头和结尾创建的所有空字符串。如果只有一个匹配项,那么它属于默认的 null 对象。否则,使用 matches 中的第一个键作为累加器中的键。

const input = ["/api/", "/docs/getting-started/", "/docs/", "/plugin/", "/plugin/user/", "/plugin/profile/"];

const mapper = input.reduce((acc, path) => {
  let matches = path.split(/\//).filter(Boolean),
      mapperKey = null;

  if (matches.length > 1)
    mapperKey = matches[0];

  if (!acc[mapperKey])
    acc[mapperKey] = { title: mapperKey, pages: [] };

  const title = matches.pop();
  acc[mapperKey].pages.push({ title, path });
  
  return acc;
}, {})

const output = Object.values(mapper);

console.log(output)