简体   繁体   English

将字符串转换为嵌套对象和数组

[英]Convert string into nested objects and arrays

I am in a project where the previous guy did some strange routing and basically I get slugs from contentful in the form of strings which I put in an array ["/api/", "/docs/getting-started/", "/docs/, "/plugin/", "/plugin/user/", "/plugin/profile/"......] 我在一个项目中,前一个家伙做了一些奇怪的路由,基本上我从满足的状态中以字符串的形式获取了子弹,这些字符串放入了数组["/api/", "/docs/getting-started/", "/docs/, "/plugin/", "/plugin/user/", "/plugin/profile/"......]

Now I need to convert it in the form of an array 现在我需要将其转换为数组形式

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/"
                      },
                     ]
               }
]

So currently what I am doing is this - 所以目前我正在做的是-

 //-------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)
                }
            }
        });
    }());
    //----------------------------------------->

I am first splitting all strings and putting the titles in a titles array then removing duplicates and mapping data accordingly. 我首先拆分所有字符串,然后将标题放入titles数组中,然后删除重复项并相应地映射数据。

I just feel like this is really bad code and there is a better way I just cannot figure out. 我只是觉得这是非常糟糕的代码,还有一种我无法弄清楚的更好的方法。

You could create a mapper object which maps the objects in the output with the title in the root of each object. 您可以创建一个mapper对象,该映射mapper将输出中的对象与每个对象根目录中的title映射。 split at the / to get all the chunks of path. /split以获取所有路径块。 .filter(Boolean) removes all the empty string created from beginning and end of the string. .filter(Boolean)删除从字符串开头和结尾创建的所有空字符串。 If there is only one match, then it belongs to the default null object. 如果只有一个匹配项,则它属于默认的null对象。 Else, use the first key in the matches as a key in the accumulator. 否则,将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) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM