打字稿:递归检查嵌套数组

时间:2019-11-13 13:47:46

标签: arrays typescript recursion nested

我在遍历嵌套数组时遇到问题,该嵌套数组可以包含本身的数组...应该代表如下动态菜单:

这是对象的制造方式:

Interface IMenuNode:

export interface IMenuNode {
    title: string;
    haveChildren: boolean;
    id: string;
    node: Array<IMenuNode>;
    link: string;
    img: string;
    value: string;
}

Class DataNode that implements IMenuNode

export class DataNode implements IMenuNode {
    title: string;
    haveChildren: boolean;
    id: string;
    node: Array<IMenuNode>;
    link: string;
    img: string;
    value: string;


userMenu: Array<IMenuNode>;

现在我在MenuData中有一些信息,如下所示:

const MenuData: Array<IMenuNode> =
    [
        new DataNode('Menu 1', true, 'menu1', [
            new DataNode('SubMenu 1', true, 'submenu1',[
                new DataNode('SubSubMenu1', false ,'subsubmenu1', null, "/", "pathSelectorIcon.png"),
                new DataNode('SubSubmenu2', false, 'subsubmenu2', null ,"/", "pathSelectorIcon.png"),
            ]),
            new DataNode('Menu 2', true, 'menu2', [
            new DataNode('SubMenu 1', true, 'submenu1',[
                new DataNode('SubSubMenu1', false ,'subsubmenu1', null, "/", "pathSelectorIcon.png"),
                new DataNode('SubSubmenu2', false, 'subsubmenu2', null ,"/", "pathSelectorIcon.png"),
            ]),

如何根据某些条件(甚至以递归方式)循环整个MenuData并动态构建新菜单(userMenu) 选择新菜单应包含的项目(菜单和子菜单)?

1 个答案:

答案 0 :(得分:0)

下面的函数显然可以满足您的期望,希望对您有所帮助。

userMenu = newUserMenu(MenuData);

function newUserMenu(original: Array<IMenuNode>): Array<IMenuNode> {
    const newMenu: Array<IMenuNode> = []
    for (let menu of original) {
        if (User.hasAccess(menu)) { // Or other conditions

            // To ensure new reference
            // Note not passing the children, it must pass through recursive method below
            const newNode = new DataNode(menu.title, menu.haveChildren, menu.id, null, menu.link, menu.img, menu.value);
            newMenu.push(newNode);
            if (newNode.haveChildren) {
                newNode.node = newUserMenu(menu.node);
            }
        }
    }
    return newMenu;
} 

我也编辑了您的类和界面,以确保构造像示例一样工作。

interface IMenuNode {
    title: string;
    haveChildren: boolean;
    id: string;
    node?: Array<IMenuNode>;
    link?: string;
    img?: string;
    value?: string;
}

class DataNode implements IMenuNode {

    constructor(
        public title: string,
        public haveChildren: boolean,
        public id: string,
        public node?: Array<IMenuNode>,
        public link?: string,
        public img?: string,
        public value?: string,
    ) { }
}

编辑:在新菜单中添加当前级别之前验证孩子的新示例。

// The new function only add the "dir" menus if they have children where the user have access
function newUserMenu2(original: Array<IMenuNode>): Array<IMenuNode> {
    const newMenu: Array<IMenuNode> = [];
    for (let menu of original) {
        if (User.hasAccess(menu)) {// Or other conditions
            // To ensure new reference
            // Note not passing the children, it must pass through recursive method below
            const newNode = new DataNode(menu.title, menu.haveChildren, menu.id, null, menu.link, menu.img, menu.value);
            if (newNode.haveChildren) {
                newNode.node = newUserMenu2(menu.node);
            }
            // Note, only add the menu if it has a link or if it "stores" a menu that the user has access and that has a link
            if (Array.isArray(newNode.node) && newNode.node.length > 0 || newNode.link) {
                newMenu.push(newNode);
            }
        }
    }
    return newMenu;
}