Javascript 过滤大型阵列(3000+;)对象
我有一个json文件,其中列出了大约3000个对象。每一个物体都是一个机场。我想创建一个函数,用户可以通过键入名称过滤出单个机场 这就是我想到的Javascript 过滤大型阵列(3000+;)对象,javascript,angular,Javascript,Angular,我有一个json文件,其中列出了大约3000个对象。每一个物体都是一个机场。我想创建一个函数,用户可以通过键入名称过滤出单个机场 这就是我想到的 <input (keyup)="searchAirport(searchquery)" [(ngModel)]="searchquery" id="searchAirport"/> <span>{{searchedAirport}}</span> 这会返回正确的Aiport名称,但有两个缺点。只有在使用大写字母搜索
<input (keyup)="searchAirport(searchquery)" [(ngModel)]="searchquery" id="searchAirport"/>
<span>{{searchedAirport}}</span>
这会返回正确的Aiport名称,但有两个缺点。只有在使用大写字母搜索时,它才有效。所以barcelona
不会返回任何内容,但是barcelona
会返回
第二个缺点是,只有当值完全等于机场名称时,它才会返回
如何基于部分搜索返回值?因此,用Bar
代替Barcelona
,我怎样才能解决资金问题呢?忽略案例:
value.toLowerCase()==i.name.toLowerCase()
对于部分搜索,您可能需要使用正则表达式(Regex)您可以按以下方式使用Regex
让arr=['abc','abd','Abe','bcd','cde','edf'];
让输入='ab';
设re=newregexp('^'+输入'i');
让结果=arr.filter(e=>e.match(re)!=null);
控制台日志(结果)代码>我会尝试以下方法:
const findMatches = (values) => test => {
const regex = new RegExp(test, 'i');
return values.filter(val => regex.test(val.name))
}
const searchAirports = findMatches(airports);
performFilter(filterBy: string): IProduct[] {
filterBy = filterBy.toLocaleLowerCase();
return this.products.filter((product: IProduct) =>
product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
}
显然,您可以内联findMatches
函数,但我认为这样更可读。要在前端搜索大量数据,我在javascript端就是这么做的-
假设您的数据数组(JSON对象)看起来像['abcd','abfer','xyds','irkd',…]
(超过100000个元素)-array1
当您从json加载数组时,创建一个javascript数组,它是一个26长度的二维数组,并在每个索引处存储每个字符的元素索引。例如,对于上述数组,您的新数组如下-[[0,1],[0,1],[0],[0,2,3],[1],[1],[],[],…]
-数组2
意思-字符“a”存在于第0个元素和第1个元素中,字符“d”存在于第0、2、3个元素中
现在,您的对象已准备就绪,页面已准备好进行快速搜索
当用户键入搜索字符串时,onkeyup可以执行此操作-
假设用户搜索'bf'
从步骤2中的数组中,加载charb
和charf
的数组,并取两者的交点。现在,您将获得所有元素的所有位置,这些元素具有charb
和charf
-相交
现在,在交集数组上进行迭代,直接在原始数组中的索引处进行操作(从步骤1开始),然后执行indexOf('bf')
//伪代码
var t=0;
$。每个(相交,函数(k,v){
if(array1[k].indexOf(searchString)>-1){
结果[t++]=array1[k];
}
});
返回结果代码>
这样,就不会迭代数组中的所有元素。您只迭代将让chars用户搜索的元素
要提供不区分大小写的搜索,请将所有内容转换为小写()
,同时准备阵列2
,并在搜索时执行以下操作:
const findMatches = (values) => test => {
const regex = new RegExp(test, 'i');
return values.filter(val => regex.test(val.name))
}
const searchAirports = findMatches(airports);
performFilter(filterBy: string): IProduct[] {
filterBy = filterBy.toLocaleLowerCase();
return this.products.filter((product: IProduct) =>
product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
}
这将执行不区分大小写的筛选,并返回包含任何已定义文本的所有项目。检查以下示例代码。这可能对你有帮助
filterData(search){
var data = [{
"id":1,
"category":"mycategory"
},
{
"id":2,
"category":"second"
},
{
"id":3,
"category": "thirdcat"
}];
return returnedData = $.grep(data, function(element, index){
search = search.toLowerCase();
var elementCategory = element.category.toLowerCase();
if(elementCategory.indexOf(search) !== -1){
return element;
}
});
}
如果它们是以Bar开头的多个匹配怎么办?那么它应该返回其中包含
Bar
的所有结果。因此,用户只需键入即可获得更具体的结果。@Caramiriel的可能重复:虽然存在一些重叠,但我不会将其称为重复。如果没有其他问题,这将增加筛选列表的整个问题。当我使用数组时,它工作正常,但当我使用数组时,我得到错误类型ERROR:e.match不是一个函数
。我的数组中的对象看起来像“代码> {ID:100”,IATA:“YOW”,ICAO:“CyOW”,Lon:“-75.669167”,…<代码>尝试.E.No.MatCH(),而不是<代码> E匹配(RE)= null (有或没有<代码> No.<代码>属性),您是否考虑过“代码> re?测试(E.NoD))。对于过滤器
,哪个似乎是更好的选择?