复杂但高效的JavaScript数组过滤
我得到了一个非常大的数组,对象(人)的结构是这样的复杂但高效的JavaScript数组过滤,javascript,arrays,filtering,Javascript,Arrays,Filtering,我得到了一个非常大的数组,对象(人)的结构是这样的 objects = [ { firstname: 'Jo', lastname : 'Brown' mail: 'jo@brown.com', courses: ['en', 'fr', 'es'] ....and a lot more... }, { firstname: 'Jack', lastname : 'Black' mail: 'blackjack@jac
objects = [
{
firstname: 'Jo',
lastname : 'Brown'
mail: 'jo@brown.com',
courses: ['en', 'fr', 'es']
....and a lot more...
},
{
firstname: 'Jack',
lastname : 'Black'
mail: 'blackjack@jackblack.win',
courses: ['en', 'fr']
....and a lot more...
},
{
firstname: 'Jeff',
lastname : 'Grey'
mail: 'grey@jeff.co.uk',
courses: ['es']
....and a lot more...
},
...and a lot more...
]
最初,我将另一个数组设置为上面的主数组,该数组应仅包含已过滤的人员:
objectsFiltered = objects;
我需要构建一个函数来过滤数组
_objectsFilters = [
{
property: ['courses']
value: ['es']
},
{
property: ['firstname', 'lastname', 'mail']
value: 'userStringInputGoesHere'
}
]
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;
}
objects = [
{
firstname: 'Jo',
lastname : 'Brown'
mail: 'jo@brown.com',
courses: ['en', 'fr', 'es']
....and a lot more...
},
{
firstname: 'Jack',
lastname : 'Black'
mail: 'blackjack@jackblack.win',
courses: ['en', 'fr']
....and a lot more...
},
{
firstname: 'Jeff',
lastname : 'Grey'
mail: 'grey@jeff.co.uk',
courses: ['es']
....and a lot more...
},
...and a lot more...
]
_objectsFilters = [
{
property: ['courses']
value: ['es']
}
]
objectsFiltered = [
{
firstname: 'Jo',
lastname : 'Brown'
mail: 'jo@brown.com',
courses: ['en', 'fr', 'es']
....and a lot more...
},
{
firstname: 'Jeff',
lastname : 'Grey'
mail: 'grey@jeff.co.uk',
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: 'blackjack@jackblack.win',
courses: ['en', 'fr']
....and a lot more...
},
]
}
]
在本例中,应过滤属性课程(数组)
包含es
且属性名字或姓氏或邮件包含UserStringInputGoeSher
的人员
我使用函数获取/设置、重置过滤器,如下所示:
_objectsFilters = [
{
property: ['courses']
value: ['es']
},
{
property: ['firstname', 'lastname', 'mail']
value: 'userStringInputGoesHere'
}
]
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;
}
objects = [
{
firstname: 'Jo',
lastname : 'Brown'
mail: 'jo@brown.com',
courses: ['en', 'fr', 'es']
....and a lot more...
},
{
firstname: 'Jack',
lastname : 'Black'
mail: 'blackjack@jackblack.win',
courses: ['en', 'fr']
....and a lot more...
},
{
firstname: 'Jeff',
lastname : 'Grey'
mail: 'grey@jeff.co.uk',
courses: ['es']
....and a lot more...
},
...and a lot more...
]
_objectsFilters = [
{
property: ['courses']
value: ['es']
}
]
objectsFiltered = [
{
firstname: 'Jo',
lastname : 'Brown'
mail: 'jo@brown.com',
courses: ['en', 'fr', 'es']
....and a lot more...
},
{
firstname: 'Jeff',
lastname : 'Grey'
mail: 'grey@jeff.co.uk',
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: 'blackjack@jackblack.win',
courses: ['en', 'fr']
....and a lot more...
},
]
}
]
将现在筛选的人员存储在数组objectsFiltered
**中,并存储由于课程筛选而未激活的剩余人员,如下所示:
_objectsFilters = [
{
property: ['courses']
value: ['es']
},
{
property: ['firstname', 'lastname', 'mail']
value: 'userStringInputGoesHere'
}
]
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;
}
objects = [
{
firstname: 'Jo',
lastname : 'Brown'
mail: 'jo@brown.com',
courses: ['en', 'fr', 'es']
....and a lot more...
},
{
firstname: 'Jack',
lastname : 'Black'
mail: 'blackjack@jackblack.win',
courses: ['en', 'fr']
....and a lot more...
},
{
firstname: 'Jeff',
lastname : 'Grey'
mail: 'grey@jeff.co.uk',
courses: ['es']
....and a lot more...
},
...and a lot more...
]
_objectsFilters = [
{
property: ['courses']
value: ['es']
}
]
objectsFiltered = [
{
firstname: 'Jo',
lastname : 'Brown'
mail: 'jo@brown.com',
courses: ['en', 'fr', 'es']
....and a lot more...
},
{
firstname: 'Jeff',
lastname : 'Grey'
mail: 'grey@jeff.co.uk',
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: 'blackjack@jackblack.win',
courses: ['en', 'fr']
....and a lot more...
},
]
}
]
通过重置某个过滤器,我可以将非活动人员复制回活动人员
哪条路是正确的道路?这看起来像是一个典型的过早优化案例
在类型A中,始终具有相同的源数据,并且始终对该数据运行一个或多个筛选器。第一个过滤器将是针对完整数据集运行的唯一过滤器;以后的过滤器将针对越来越小的集合运行(因为一些数据已经被过滤掉了)
在类型B中,每次运行筛选器时都要修改源数据,并将筛选出的元素存储在单独的数组中。正如您所描述的,它将不起作用:如果过滤器发生更改,则无法知道哪些元素需要从存储中恢复到源数组中(因为您无法分辨哪个过滤器删除了每个对象)。我能想到的“最简单”的工作方法是为每个过滤器保留一个单独的存储,因此当filter X发生变化时,您会将filter-by-X的存储中的所有对象转储回源中,然后重新运行filter X。这可以工作,但维护起来相当复杂
首先编写简单方法的代码。如果没有性能问题,就完成了
如果您确实存在性能问题,请不要直接跳到方法B:相反,调整执行过滤器的顺序:如果给定的过滤器可能会删除比其他过滤器更多的数据,请先执行。如果一个过滤器在计算上很昂贵,那么最后再做
如果您仍然存在性能问题,那么您可以进入实现方法B所涉及的英雄(不会是这样的。如果您处理的客户端数据太多,以致于您在过滤它时存在性能问题,那么您已经有了更大的性能问题,只需首先下载它…)这看起来像是一个典型的过早优化案例
在类型A中,始终具有相同的源数据,并且始终对该数据运行一个或多个筛选器。第一个过滤器将是针对完整数据集运行的唯一过滤器;以后的过滤器将针对越来越小的集合运行(因为一些数据已经被过滤掉了)
在类型B中,每次运行筛选器时都要修改源数据,并将筛选出的元素存储在单独的数组中。正如您所描述的,它将不起作用:如果过滤器发生更改,则无法知道哪些元素需要从存储中恢复到源数组中(因为您无法分辨哪个过滤器删除了每个对象)。我能想到的“最简单”的工作方法是为每个过滤器保留一个单独的存储,因此当filter X发生变化时,您会将filter-by-X的存储中的所有对象转储回源中,然后重新运行filter X。这可以工作,但维护起来相当复杂
首先编写简单方法的代码。如果没有性能问题,就完成了
如果您确实存在性能问题,请不要直接跳到方法B:相反,调整执行过滤器的顺序:如果给定的过滤器可能会删除比其他过滤器更多的数据,请先执行。如果一个过滤器在计算上很昂贵,那么最后再做
如果您仍然存在性能问题,那么您可能会在实现方法B的过程中遇到困难(不会出现这种情况。如果您处理的客户端数据太多,以致于您在过滤数据时遇到性能问题,那么您在一开始下载数据时就已经遇到了更大的性能问题……“类型A”听起来更容易实现。就我个人而言,如果你遇到性能问题,我会走这条路,重新评估IIP。也要考虑的事实是,非常聪明的人已经解决了这些问题很多次,而其他人广泛使用的,经过验证的解决方案几乎总是比我们自己写的更好。(换句话说,用简单的方法来做,如果你发现你需要更强大的东西,不要重新发明轮子。)“A型”听起来更容易实现。就我个人而言,如果你遇到性能问题,我会走这条路,重新评估IIP。也要考虑的事实是,非常聪明的人已经解决了这些问题很多次,而其他人广泛使用的,经过验证的解决方案几乎总是比我们自己写的更好。(换句话说,用简单的方法来做,如果你发现你需要更强大的东西,不要重新发明轮子。)