递归检查是否有活动的子节点



我有一个递归列表的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;
}

编辑:当一个项目只有最大一个子项时,它工作得很好,但是,经过更深入的测试,我发现该方法及其返回值在应用于较大的嵌套结构时失败。因此,仍有改进的余地。

最新更新