复杂的分组:数组 Reduce

4
我很困惑如何使用array.reduce(),尤其是在这种情况下,我不确定是否有正确的方法。通常我有一个起始数组,并且知道我需要什么结果,但我似乎无法正确分组。
这是起始数组:
[
{ name: 'Home' },
{
    name: 'Services',
    menu: [
    { name: 'Painting' },
    { name: 'Decorating' },
    { name: 'Lawn mowing', submenu: 'Garden' },
    { name: 'Tree surgery', submenu: 'Garden' },
    { name: 'Edging', submenu: 'Garden' }
    ]
},
{ name: 'Contact' }
]

我希望最终得到的是这个

[
{ name: 'Home' },
{
    name: 'Services',
    menu: [
    { name: 'Painting' },
    { name: 'Decorating' },
    {
        name: 'Garden',
        menu: [
        { name: 'Lawn mowing', submenu: 'Garden' },
        { name: 'Tree surgery', submenu: 'Garden' },
        { name: 'Edging', submenu: 'Garden' }
        ]
    }
    ]
},
{ name: 'Contact' }
]

所以我希望能够按具有子菜单的任何内容进行分组,然后返回一个新的排序数组。

2个回答

2
尝试以下递归方法:

function reduce(array) {
    const result = [];
    // object to keep grouped submenus
    const grouped = {};
    for (let i of array) {
        if (i.menu) {
            // if the current item has a nested menu we call reduce recursively
            result.push({
                name: i.name,
                menu: reduce(i.menu)
            });
        } else if (i.submenu) {
            // if it has a submenu we put it to the grouped object
            if (grouped[i.submenu]) {
                grouped[i.submenu].menu.push(i)
            } else {
                grouped[i.submenu] = {
                    name: i.submenu,
                    menu: [i]
                };
                result.push(grouped[i.submenu]);
            }
        } else {
            // else we just copy it to the result array
            result.push(i);
        }
    }
    return result;
}

const array = [
    { name: 'Home' },
    {
        name: 'Services',
        menu: [
            { name: 'Painting' },
            { name: 'Decorating' },
            { name: 'Lawn mowing', submenu: 'Garden' },
            { name: 'Tree surgery', submenu: 'Garden' },
            { name: 'Edging', submenu: 'Garden' }
        ]
    },
    { name: 'Contact' }
];

console.log(reduce(array));


1
谢谢Kirill!这太棒了! - Paul

2
您可以通过查找子菜单并将其用作实际级别节点的搜索来缩小数组。
如果没有,只需添加一个新对象或具有递归调用中的菜单的对象。

function mapSubmenu(result, { name, menu, submenu }) {
    if (submenu) {
        var parent = result.find(({ name }) => name === submenu);
        if (!parent) result.push(parent = { name: submenu, menu: [] });
        parent.menu.push({ name, submenu });
    } else {
        result.push(menu
            ? { name, menu: menu.reduce(mapSubmenu, []) }
            : { name }
        );
    }
    return result;
}

var data = [{ name: 'Home' }, { name: 'Services', menu: [{ name: 'Painting' }, { name: 'Decorating' }, { name: 'Lawn mowing', submenu: 'Garden' }, { name: 'Tree surgery', submenu: 'Garden' }, { name: 'Edging', submenu: 'Garden' }] }, { name: 'Contact' }],
    result = data.reduce(mapSubmenu, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接