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

标签 javascript angular ecmascript-6 angular8

我正在尝试根据大子数组的值过滤父数组,但我的过滤方法效果不佳,而且 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
    )
}

Live Demo

期望:

当用户键入new Course时,它应该只在 Program 列中显示 DP Programme

最佳答案

您可以通过组合使用 map 来实现此目的, filtersome 数组 方法。使用扩展运算符 ... 以便您的原始数组不会在子对象中更新。

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/

相关文章:

javascript - JavaScript 中的生成器和闭包有什么区别?

javascript - 使用 ES6 语法定义类方法属性

javascript - Angular 嵌套 Controller 错误

javascript - firebug 显示 js 从静态文件正确加载,但它不起作用(Django)

javascript - 如何在 dataTable.js 中转置行和列

javascript - 如何使用给定的原型(prototype)链创建对象?

Angular 未捕获类型错误 : e is not a constructor after build --prod (work on ng serve)

node.js - 如何在模块 A 导入模块 B 的地方开发两个 Angular 模块

javascript - 如何在将对象属性作为参数传递时使用连字符

javascript - 重构 map、reduce 和 double for 循环 - javascript es6