复杂的,但有效的JavaScript数组过滤

问题描述:

我有一个非常大的阵列的对象(人)的结构这样复杂的,但有效的JavaScript数组过滤

objects = [ 
    { 
    firstname: 'Jo', 
    lastname : 'Brown' 
    mail: '[email protected]', 
    courses: ['en', 'fr', 'es'] 

    ....and a lot more... 
    }, 
    { 
    firstname: 'Jack', 
    lastname : 'Black' 
    mail: '[email protected]', 
    courses: ['en', 'fr'] 
    ....and a lot more... 
    }, 
    { 
    firstname: 'Jeff', 
    lastname : 'Grey' 
    mail: '[email protected]', 
    courses: ['es'] 
    ....and a lot more... 
    }, 

    ...and a lot more... 
] 

最初予置另一阵列,其应包含过滤人员仅于上述主阵列:

objectsFiltered = objects; 

我需要构建一个功能来过滤与

  1. 字符串通过键入到一个文本框该阵列该应用程序的用户(搜索输入)
  2. 某些其它准则可选择通过链接或下拉菜单...

因此我激活的过滤器存储在另一个阵列是这样的:

_objectsFilters = [ 
    { 
    property: ['courses'] 
    value: ['es'] 
    }, 
    { 
    property: ['firstname', 'lastname', 'mail'] 
    value: 'userStringInputGoesHere' 
    } 
] 

在这个例子中的人,其财产courses (Array)包含es和其财产firstnameORlastnameORmail包含应该过滤。

我用函数来获取/套,过滤器复位这样的:

public set objectsFilters(objectsFilters: Array<ObjectsFilters>) { 
    for (let filter of objectsFilters) { 
    let index = this._objectsFilters.indexOf(filter); 

    /* add filter if not already active */ 
    if(index === -1) { 
     this._objectsFilters.push(filter); 
     continue; 
    } 

    /* remove filter if active already */ 
    this._objectsFilters.splice(index, 1); 
    } 
} 

public get objectsFilters(): Array<ObjectsFilters> { 
    return this._nobjectsFilter; 
} 

最后,问题

这是复位过滤器和与之的filteredObjects(人)的最佳途径。我想到了两种方式管理这样的:每次

A型

使用其他功能来设置过滤的对象(人)阵列objectsFilters变化。因此该函数将始终使用包含ALL个人(objects)的未修改阵列并应用所有过滤器。 (效率??!)

类型B

如果某一个过滤器从上方施加例如第一过滤器:

{ 
    property: ['courses'], 
    value: ['es'] 
}, 

商店现在过滤人员阵列objectsFiltered中**并存储由于课程过滤器而不活动的其余人员,如下所示:

objects = [ 
    { 
    firstname: 'Jo', 
    lastname : 'Brown' 
    mail: '[email protected]', 
    courses: ['en', 'fr', 'es'] 

    ....and a lot more... 
    }, 
    { 
    firstname: 'Jack', 
    lastname : 'Black' 
    mail: '[email protected]', 
    courses: ['en', 'fr'] 
    ....and a lot more... 
    }, 
    { 
    firstname: 'Jeff', 
    lastname : 'Grey' 
    mail: '[email protected]', 
    courses: ['es'] 
    ....and a lot more... 
    }, 

    ...and a lot more... 
] 

_objectsFilters = [ 
    { 
    property: ['courses'] 
    value: ['es'] 
    } 
] 

objectsFiltered = [ 
    { 
    firstname: 'Jo', 
    lastname : 'Brown' 
    mail: '[email protected]', 
    courses: ['en', 'fr', 'es'] 

    ....and a lot more... 
    }, 
    { 
    firstname: 'Jeff', 
    lastname : 'Grey' 
    mail: '[email protected]', 
    courses: ['es'] 
    ....and a lot more... 
    }, 

    ...and a lot more... 
] 

inactiveObjects = [ 
    { 
    inactiveCause: { 
     property: ['courses'], 
     value: ['es'] 
    }, 
    /* containing all objects inactive because of the above filter */ 
    objects: [ 
     { 
     firstname: 'Jack', 
     lastname : 'Black' 
     mail: '[email protected]', 
     courses: ['en', 'fr'] 
     ....and a lot more... 
     }, 
    ] 
    } 
] 

这样通过re设置一个特定的过滤器我可以将非活动人员复制回活动人员。

哪种方式是正确的路?

+0

“类型A”听起来更容易实现。就我个人而言,如果遇到性能问题,我会走这条路线并重新评估。还要考虑一个事实,即非常聪明的人已经多次解决了这些问题,而其他人的广泛使用,经过充分测试的解决方案几乎总是比我们自己写的更好。 (换句话说,以简单的方式来做,如果你发现你需要更强大的东西,不要重新发明轮子。) –

这看起来像是过早优化的经典案例。

在类型A中,您始终拥有相同的源数据,并始终对该数据运行一个或多个过滤器。第一个过滤器将是唯一一个针对完整数据集运行的过滤器;后面的过滤器将针对逐渐变小的集合运行(因为某些数据已经被过滤掉了)。

在B类中,您每次运行过滤器时都要修改源数据,并存储过滤掉的数据元素在一个单独的数组中。正如你所描述的那样,它不起作用:如果过滤器发生变化,无法知道哪些元素需要从存储器恢复到源数组中(因为您无法知道哪个过滤器会删除每个对象)。我能想到的“最简单”的工作方法是为每个过滤器保留一个单独的存储空间,因此当过滤器X发生更改时,您需要将所有对象从过滤后的X存储回源,然后重新运行过滤器X 。这会起作用,但维护起来会相当复杂。

首先编写简单的方法A.如果你没有性能问题,你就完成了。

如果您确实有性能问题,请不要直接跳到方法B:而是调整您执行过滤器的顺序:如果给定的过滤器可能会比其他过滤器移除更多数据,请先执行此操作。如果一个过滤器在计算上花费很大,那么继续使用它。

如果你仍然有性能问题,那么你也许可以进入参与实施方法B的英雄(它不会来到这个如果你处理如此多的数据客户端,你有性能问题过滤它,你已经有更大的性能问题,只是首先下载它...)