[英]filter through deeply nested object array with array of values in javascript
[英]Filter a JavaScript deeply nested array of objects based on its values
我有一個菜單結構如下:
const menu = [
{
title: 'Supervisor Dashboard',
link: '/dashboard/supervisor-dashboard',
slug: '/dashboard/supervisor-dashboard'
},
{
title: 'User Dashboard',
link: '/dashboard/user-dashboard',
slug: '/dashboard/user-dashboard'
},
{
title: 'Inventory',
slug: '/inventory',
children: [
{
title: 'Add Inventory',
link: '/inventory/add-inventory',
slug: '/inventory/add-inventory'
},
{
title: 'Remove Inventory',
link: '/inventory/remove-inventory',
slug: '/inventory/remove-inventory'
},
]
},
{
title: 'Membership',
slug: '/membership',
children: [
{
title: 'Program A',
slug: '/membership/program-a',
children: [
{
title: 'View Membership',
link: '/membership/program-a/view',
slug: '/membership/program-a/view'
},
{
title: 'Add Membership',
link: '/membership/program-a/add',
slug: '/membership/program-a/add'
},
{
title: 'Delete Membership',
link: '/membership/program-a/delete',
slug: '/membership/program-a/delete'
}
]
},
{
title: 'Program B',
slug: '/membership/program-b',
children: [
{
title: 'View Membership',
link: '/membership/program-b/view',
slug: '/membership/program-b/view'
},
{
title: 'Add Membership',
link: '/membership/program-b/add',
slug: '/membership/program-b/add'
},
{
title: 'Delete Membership',
link: '/membership/program-b/delete',
slug: '/membership/program-b/delete'
}
]
}
],
},
];
我想過濾菜單,即僅顯示授予用戶的任何內容。 用戶只能根據允許的slugs查看菜單,如下所示:
const allowed_slug = [
'/dashboard/user-dashboard',
'/inventory/add-inventory',
'/membership/program-b/view',
'/membership/program-b/add'
];
使用.filter
我能夠過濾數組的第一層。 這是我到目前為止取得的成就:
function filterMenu(menus, allowed_slug) {
const result = menus.filter(function (menu_item) {
return allowed_slug.filter(function(slug) {
return menu_item.slug.indexOf(slug) > -1;
}).length;
});
return result;
}
理想輸出應如下所示:
o
|-- User Dashboard
|-- Inventory
| `-- Add Inventory
`-- Membership
`-- Program B
|-- View Membership
`-- Add Membership
問題是,我無法過濾嵌套數組,即兒童和兒童。 很感謝任何形式的幫助。 :)
您可以檢查一個allowdSlug
是否以實際對象的slug開頭。
var menus = [{ title: 'Supervisor Dashboard', link: '/dashboard/supervisor-dashboard', slug: '/dashboard/supervisor-dashboard' }, { title: 'User Dashboard', link: '/dashboard/user-dashboard', slug: '/dashboard/user-dashboard' }, { title: 'Inventory', slug: '/inventory', children: [{ title: 'Add Inventory', link: '/inventory/add-inventory', slug: '/inventory/add-inventory' }, { title: 'Remove Inventory', link: '/inventory/remove-inventory', slug: '/inventory/remove-inventory' }] }, { title: 'Membership', slug: '/membership', children: [{ title: 'Program A', slug: '/membership/program-a', children: [{ title: 'View Membership', link: '/membership/program-a/view', slug: '/membership/program-a/view' }, { title: 'Add Membership', link: '/membership/program-a/add', slug: '/membership/program-a/add' }, { title: 'Delete Membership', link: '/membership/program-a/delete', slug: '/membership/program-a/delete' }] }, { title: 'Program B', slug: '/membership/program-b', children: [{ title: 'View Membership', link: '/membership/program-b/view', slug: '/membership/program-b/view' }, { title: 'Add Membership', link: '/membership/program-b/add', slug: '/membership/program-b/add' }, { title: 'Delete Membership', link: '/membership/program-b/delete', slug: '/membership/program-b/delete' }] }] }], allowed_slug = ['/dashboard/user-dashboard', '/inventory/add-inventory', '/membership/program-b/view', '/membership/program-b/add'], filter = menus => menus .filter(({ slug }) => allowed_slug.some(s => s.startsWith(slug))) .map(({ title, slug, children = [] }) => { children = filter(children); return Object.assign({ title, slug }, children.length && { children }) }), result = filter(menus); console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
遞歸是你的朋友:
// smae signature as your function
const filterMenu = (menus, allowed) => menus
// first of all, copy & filter recursively
.map(({ title, slug, link, children }) => ({ title, slug, link, children: children && filterMenu(children, allowed) }))
// then remove all that don't have allowed children and are not allowed themself
.filter(it => it.children && it.children.length || allowed.includes(it.slug));
嘗試使用此功能,看看它是否符合您的需求。 它基本上使用遞歸reduce函數創建一個新數組,檢查每個元素是否與slugs數組的條件匹配:
const menu = [ { title: 'Supervisor Dashboard', link: '/dashboard/supervisor-dashboard', slug: '/dashboard/supervisor-dashboard' }, { title: 'User Dashboard', link: '/dashboard/user-dashboard', slug: '/dashboard/user-dashboard' }, { title: 'Inventory', slug: '/inventory', children: [ { title: 'Add Inventory', link: '/inventory/add-inventory', slug: '/inventory/add-inventory' }, { title: 'Remove Inventory', link: '/inventory/remove-inventory', slug: '/inventory/remove-inventory' }, ] }, { title: 'Membership', slug: '/membership', children: [ { title: 'Program A', slug: '/membership/program-a', children: [ { title: 'View Membership', link: '/membership/program-a/view', slug: '/membership/program-a/view' }, { title: 'Add Membership', link: '/membership/program-a/add', slug: '/membership/program-a/add' }, { title: 'Delete Membership', link: '/membership/program-a/delete', slug: '/membership/program-a/delete' } ] }, { title: 'Program B', slug: '/membership/program-b', children: [ { title: 'View Membership', link: '/membership/program-b/view', slug: '/membership/program-b/view' }, { title: 'Add Membership', link: '/membership/program-b/add', slug: '/membership/program-b/add' }, { title: 'Delete Membership', link: '/membership/program-b/delete', slug: '/membership/program-b/delete' } ] } ], }, ]; const allowed_slug = [ '/dashboard/user-dashboard', '/inventory/add-inventory', '/membership/program-b/view', '/membership/program-b/add' ]; const filterMenu = (menu, allowed) => menu.reduce((a, {title, link, slug, children = []}) => (children = filterMenu(children, allowed), (children.length && (a = [...a, {title, slug, children}])) || (allowed.includes(slug) && (a = [...a, {title, link, slug}])), a), []); console.log(filterMenu(menu, allowed_slug));
該函數的可讀性更強:
const filterMenu = (menu, allowed) =>
menu.reduce((array, {title, link, slug, children = []}) => {
children = filterMenu(children, allowed);
if (children.length) {
array.push({title, slug, children});
} else if (allowed.includes(slug)) {
array.push({title, link, slug});
}
return array;
}, []);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.