我有一个递归列表的items
在Angular/TypeScript和我试图只显示items
时,他们是active=true;
本身或如果任何孩子或孩子的孩子是active=true
;
data.json
[
{
"active": true, // active and some children active => show
"items": [
{
"active": false, // not active and no children active => don´t show
"items": [
{
"active": false,
"items": []
},
{
"active": false,
"items": []
}
]
},
{
"active": false, // not active but some children active => show
"items": [
{
"active": true,
"items": []
}
]
},
{
"active": true, // active and some children active => show
"items": [
{
"active": true,
"items": []
}
]
}
]
}
]
这是我当前的递归方法,然而,它仍然不能用于嵌套项,当我将最深的项设置为active=false;
时,它为所有父项返回false
这是因为当item
有子代时,它只会继续递归(return this.hasActiveChildren(i);
)而不考虑当前的item.active
。
method.ts
public hasActiveChildren(item: Item): boolean {
if (item.items === null || item.items.length <= 0) {
return false;
}
return item.items.some(i => {
if (i.items === null || i.items.length <= 0) {
return i.active;
} else {
return this.hasActiveChildren(i);
}
});
}
第二个方法效果更好,如果所有直接子节点都是active=false;
,则返回父节点的false
。然而,它仍然没有考虑到孩子的孩子。
updatedMethod.ts
public hasActiveChildren(item: Item): boolean {
for (const i of item.items) {
if (i.active === true) {
return true;
} else if(i.items=== null || i.items.length <= 0) {
return this.hasActiveChildren(i);
}
}
return false;
}
也许我需要指定:
- 我有一个深度未知的
items
递归列表 - 每个
item
都有一个active
属性 - 我想创建一个方法,当
item
的任何子代或子代的子代的active
属性为true
时返回true
- 我已经创建了两个方法来解决这个问题,但不能使它完全工作
您当前的方法的问题是,您只检查如果父不是活动的子。您希望每次或在检查父节点是否活动之前递归地检查子节点。我使用了以下接口:
export interface Item {
active: boolean,
items: Item[]
}
这是一个使用filter
的实现,它将递归地调用之前所有子节点的函数,并返回item.items
中所有活动项的数组。使用||
将显示该项目,如果任何一个子项目是活动的或当前项目是活动的。这里的关键是在递归检查子节点之后检查item.active
。
function shouldShowItem(item: Item): boolean {
const result: boolean = item.items.filter(i => shouldShowItem(i)).length > 0 || item.active;
// Logic to display the item here based on result
return result;
}
这是另一个可能更清楚的选项。结果初始化为active
的值,然后递归检查所有子节点。如果任何子节点都是活动的,该值将被覆盖为true。
function shouldShowItem(item: Item): boolean {
let result: boolean = item.active;
for (let i of item.items) {
if (shouldShowItem(i)) {
result = true;
}
}
// Logic to display the item here based on result
return result;
}
花了一些时间后,我想出了下面的递归方法。从性能上看,这似乎是可行的。
method.ts
public hasActiveChildren(item: Item): boolean {
// if the item has no sub items, always return false
if (item.items == null || item.items.length < 0) {
return false;
}
for (const i of item.items) {
// if any sub item is active, always return true
if (i.active === true) {
return true;
} else {
// else, repeat the process
return this.hasActiveChildren(i);
}
}
// default return value due to compiler errors
return false;
}
编辑:当一个项目只有最大一个子项时,它工作得很好,但是,经过更深入的测试,我发现该方法及其返回值在应用于较大的嵌套结构时失败。因此,仍有改进的余地。