我正在尝试根据大子数组的值过滤父数组,但我的过滤方法效果不佳,而且 UI 没有得到更新。
这是我的过滤函数。
filterIt($event) {
this.filter.RegCategoryName = $event.target.value;
this.dataObject = staticData.filter(value =>
value.List.filter(ch => ch.RegistrationCategory.filter(gChild =>
Object.keys(this.filter).every(ob =>
String(gChild[ob]).toLowerCase().includes(String(this.filter[ob]).toLowerCase())
)
)).length
)
}
期望:
当用户键入new Course
时,它应该只在 Program 列中显示 DP Programme
。
最佳答案
您可以通过组合使用 map
来实现此目的, filter
和 some
数组
方法。使用扩展运算符 ...
以便您的原始数组不会在子对象中更新。
filterIt($event) {
this.filter.RegCategoryName = $event.target.value;
this.dataObject = staticData.filter(value => {
const data = { ...value };
data.List = data.List.map(ch => {
const list = { ...ch };
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().indexOf(this.filter.RegCategoryName.toLowerCase()) !== -1
});
return list;
});
return data.List.some(list => !!list.RegistrationCategory.length);
});
}
注意:避免使用首字母大写的变量名。
这是关于 StackBlitz 的工作示例.
解释:
这里使用的结构非常复杂,所以我想我会从里到外开始。让我们从最里面的 filter
开始。
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().indexOf(this.filter.RegCategoryName.toLowerCase()) !== -1
});
The
filter()
method creates a new array with all elements that pass the test implemented by the provided function.
这个应该够清楚了吧。此处使用的条件与 Angular Material 的 mat-table
过滤器中使用的条件相同。如果 RegCategoryName
包含搜索词,这将进行过滤。我说包含是因为这将匹配 new Course
,即使您的搜索词是 ew
。如果这不是您想要的,您可以改用 startsWith
。仅当您的搜索词是 new
而不是 ew
时才会匹配。
list.RegistrationCategory = list.RegistrationCategory.filter(gChild => {
return gChild.RegCategoryName.toLowerCase().startsWith(this.filter.RegCategoryName.toLowerCase())
});
转到第一个父数组 List
。我们不想过滤
或更改此处的对象。相反,我们只需要相同的对象,但使用新的过滤 RegistrationCategory
。这非常适合 map
,因为 map
返回一个包含相同数量对象的数组(如果需要,可以对对象中的元素进行一些修改)。
The
map()
method creates a new array with the results of calling a provided function on every element in the calling array.
所以在我们的 map
中,我们将使用上面创建的 filter
更新 RegistrationCategory
。我们不能直接修改 ch
,因为那样会改变原始对象。因此,我们将使用 spread syntax 浅层克隆 ch
进入变量 list
,使用上述 filter
修改新 list
变量中的 RegistrationCategory
并返回对象。这现在通过更新每个对象中的 RegistrationCategory
为我们提供了 List
数组。
现在是最后一部分,我们需要通过 staticData
进行过滤
。正如我们在 map
中所做的那样,我们将在此处再次使用展开语法,因为我们不想更新原始对象。由于我们最里面的过滤器,data.List
现在将过滤每个 RegistrationCategory
,所以我们只需要返回一个 true
/false
值基于 List
数组是否有任何 RegistrationCategory
长度大于 0 的对象。我们可以为此使用 some
。
The
some()
method tests whether at least one element in the array passes the test implemented by the provided function. It returns a Boolean value.
因此,如果 List
数组中的任何 RegistrationCategory
的长度大于 0(因为这就是我们所关心的,是否任何 RegistrationCategory
仍然是在我们最里面的过滤器过滤完 List
之后出现),它返回 true
并添加到过滤后的 dataObject
。
通过这种方式,我们可以获取 staticData
中的每个对象,其 List
数组包含一个对象,其中 RegistrationCategory
具有一些数据。
我希望这可以清楚地说明为什么您的代码有问题以及为什么不能对所有三个数组使用过滤器。
关于javascript - 如何根据大子数组的值过滤数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58060126/