如何根据大子数组的值过滤数组?

时间:2019-09-23 10:13:03

标签: javascript angular ecmascript-6 angular8

我正在尝试根据大子数组的值来过滤父数组,但是我的过滤方法无法正常工作,并且用户界面没有得到更新。

这是我的过滤器功能。

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
    )
}

Live Demo

期望:

当用户键入new Course时,它应仅在“程序”列中显示DP Programme

1 个答案:

答案 0 :(得分:2)

您可以结合使用mapfiltersome Array方法来实现。使用扩展运算符...,以使原始数组不会在子对象中得到更新。

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
});
  

filter() 方法创建一个新数组,其中包含所有通过由提供的功能实现的测试的元素。

这应该足够清楚。此处使用的条件与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。我们不想filter或在此处更改对象。取而代之的是,我们只需要同一个对象,但是要使用新的过滤后的RegistrationCategory。这很适合map,因为map返回的数组具有相同数量的对象(如果需要,可以对对象中的元素进行一些修改)。

  

map() 方法创建一个新数组,其结果是在调用数组中的每个元素上调用提供的函数。

因此,在我们的map中,我们将使用上面创建的RegistrationCategory更新filter。我们无法直接修改ch,因为那样会改变原始对象。因此,我们将使用spread syntaxch浅克隆到变量list中,并使用上述RegistrationCategory在新的list变量中修改filter并返回对象。现在,只需更新每个对象中的List,就可以为我们提供RegistrationCategory数组。

现在,作为最后一部分,我们需要从filterstaticData。就像我们在map中所做的那样,由于我们不想更新原始对象,因此将在此处再次使用传播语法。 data.List现在将通过内部过滤器对每个RegistrationCategory进行过滤,因此我们只需要根据true数组是否返回一个false / List值包含RegistrationCategory长度大于0的任何对象。为此,我们可以使用some

  

some() 方法测试数组中的至少一个元素是否通过了由提供的函数实现的测试。它返回一个布尔值。

因此,如果RegistrationCategory数组中的任何List的长度都大于0(因为这是我们关心的全部,那么在我们最里面的过滤器过滤{{ 1}}),则返回RegistrationCategory,并将其添加到过滤后的List中。

通过这种方式,我们得到true的每个对象,它们的dataObject数组包含一个对象,其中staticData包含一些数据。

我希望这可以弄清楚为什么您的代码有问题以及为什么不能对所有三个数组使用过滤器。