[英]Filtering item from nested object array in typescript
我已经寻找示例了一段时间,但是找不到任何类似的东西,而且我对过滤器功能的了解不足,非常感谢。 我正在尝试从嵌套项目标签===未定义的对象中删除元素。
this.items = [ // main MenuItem[] object (contains entire menu)
{
label: this.headingLabel, visible: this.booleanPipe.transform(this.labelVisible),
items: [ // headings of the menu sit in navbar, a MenuItem[][] two dimensional array
[
{
label: this.subMenuLabel, visible: this.booleanPipe.transform(this.labelVisible), separator: true,
items: [ // items that need to be removed if they are undefined, another MenuItem[] object, potentially need to remove only some of its elements
{ label: this.subMenuItemLabel, visible: this.booleanPipe.transform(this.labelVisible) },
{ label: this.subMenuItemLabel, visible: this.booleanPipe.transform(this.labelVisible) },
{ label: undefined, visible: this.booleanPipe.transform(this.labelVisible) },
{ label: this.subMenuItemLabel, visible: this.booleanPipe.transform(this.labelVisible) },
{ label: this.subMenuItemLabel, visible: this.booleanPipe.transform(this.labelVisible) },
{ label: undefined, visible: this.booleanPipe.transform(this.labelVisible) }
]
},
],
[
{
label: subMenuLabel, visible: this.booleanPipe.transform(this.labelVisible), separator: true,
items: [
{ label: subMenuItemLabel, visible: this.booleanPipe.transform(this.labelVisible) },
{ label: subMenuItemLabel, visible: this.booleanPipe.transform(this.labelVisible) },
{ label: subMenuItemLabel, visible: this.booleanPipe.transform(this.labelVisible) }
]
}
]
]
},
...
我可以使用以下方法从未定义标签的主要对象中删除元素:
this.items = this.items.filter(obj => obj.label !== undefined);
但是我无法弄清楚如何嵌套另一个过滤器,映射或查找...不确定如何..才能访问嵌套项并检查其未定义标签并删除它们!
EDIT1: this.items对象是一个MenuItem []数组。 MenuItem是PrimeNG类。 它具有以下定义:
export interface MenuItem {
label?: string;
icon?: string;
command?: (event?: any) => void;
url?: string;
routerLink?: any;
queryParams?: { [k: string]: any };
items?: MenuItem[]|MenuItem[][];
expanded?: boolean;
disabled?: boolean;
visible?: boolean;
target?: string;
routerLinkActiveOptions?: any;
separator?: boolean;
badge?: string;
badgeStyleClass?: string;
style?:any;
styleClass?:string;
title?: string;
id?: string;
automationId?: any;
}
为了构造MegaMenu组件,您必须在打字稿文件中定义您的结构,由于这不是我的要求,因此我无法脱离它。 我也无法从PrimeNG的库中选择另一个菜单组件。 希望我的进一步解释对您有所帮助,对不起,如果我起初不清楚。 我想专注于这个问题,而不会使这个问题复杂化。
this.items = [ //main MenuItem[] contains the entire menu
{
label: label1, visible: this.booleanPipe.transform(this.labelVisible),
items: [ //nested MenuItem[][] contains the headings and each individual menu list for headings
[
{
label: this.label2, visible: this.booleanPipe.transform(this.labelVisible), separator: true,
items: [ //another MenuItem[] (contains dropdowns, subheadings etc)
{ label: this.label3, visible: this.booleanPipe.transform(this.labelVisible) },
希望能够删除最嵌套的内部项目对象的主要原因是,即使您将其显示为可见,Angular仍会在菜单中呈现空白点:false。 这使菜单看起来非常非常丑陋且分散。
感谢到目前为止的所有建议并帮助弥补我的一些知识空白,我将在明天尝试实施所有建议的想法并进行报告。 希望我的编辑内容更加清晰。
编辑:我今天要签字,最近的尝试是我这样做了,但没有成功:
for (let item of this.items) {
for (let subItem of item.items) {
subItem = (subItem as (MenuItem)[]).filter(obj => obj.label !== undefined);
}
}
使用reduce
创建包含所有元素的单个列表,然后进行过滤。
使用如下递归调用:
private filterItems(items:Array){
return this.items.filter(obj => obj.label !== undefined)
.forEach(item=> if(item.items) {item.items=this.filterArray(item.items)};
}
第一次调用items=this.filterItems(items)
正如我在这里没有编译器帮助的情况下写的那样,这可能需要修复。
只是我们很清楚,您的数据如下所示:
interface Item {
label?: string;
visible: boolean;
}
interface MiddleItem {
label?: string;
visible: boolean;
separator: boolean;
items?: Item[];
}
interface TopItem {
label?: string;
visible: boolean;
items?: MiddleItem[][];
}
interface Scope {
items?: TopItem[];
}
根据您的示例代码,您想要修改原始数据。 这使算法稍微简单一些(或者,您可以先进行深度复制,然后再执行此操作)
逐步,您要:
检查标签是否未定义
如果是这样,请删除该条目
如果不是,则以“相同”方式处理子项
如果只有一个接口,那么以递归的方式进行操作将非常容易,但是您的子项都是不同的签名,并且您知道自己的深度,所以让它拼写出来而不是做任何花哨的事情。
从入口点开始:
processScope(this);
function processScope(scope: Scope) {
if(!scope.items) return;
scope.items = scope.items.filter(processTop); // basically your initial start
}
// this function gets called for each array entry in top.items
// normally you see filter as using just the simplified boolean test function
// but here we are going to have it preform a side effect - modifying the contents!
// splitting this out to its own named function makes it easier to read / document
function processTop(top: TopItem): boolean {
if (!top.label) return false; // do not include in filtered array
if (top.items) {
top.items = top.items
.map(processMiddleArr) // process each subarray
.filter(middleArr => middleArr.length !== 0); // map might have replaced the subarray with an empty array - filter those out
return true; // include in filtered array
}
// this gets called for each array entry in top.items
// since top.items is a two dimensional array, this is just another array to iterate
function processMiddleArr(middleArr: MiddleItem[]): MiddleItem[] {
return middleArr.filter(processMiddle);
}
function processMiddle(middle: MiddleItem): boolean {
if (middle.label === undefined) return false; // do not include in filtered array
// here's another side effect, filtering the lowest level item list
if (middle.items) middle.items = middle.items.filter(processItem);
return true; // include in filtered array
}
// broken out into its own function for consistency with the above filter calls
// this would be fine to do inline as middle.items.filter(it => !!item.label)
function processItem(item: Item): boolean {
if (item.label === undefined) return false; // do not include in filtered array
return true; // include in filtered array
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.