【问题标题】:Filter through large arrray (3000+) objects过滤大型数组(3000+)对象
【发布时间】:2018-07-06 18:56:33
【问题描述】:

我有一个 json 文件,其中列出了大约 3000 个对象。每个物体都是一个机场。我想创建一个功能,用户可以通过输入名称过滤出单个机场。

这是我想出来的

<input (keyup)="searchAirport(searchquery)" [(ngModel)]="searchquery" id="searchAirport"/>
<span>{{searchedAirport}}</span>

组件

searchedAirport: string;

this.http.request('/assets/resources/airportsraw.json')
  .map(res => res.json())
  .subscribe(data => {
      this.airportsArray = data;
  });

searchAirport(value) {
  for (const i of this.airportsArray) {
    if (value === i.name ) {
      this.searchedAirport = i.name;
    }
  }
}

这确实返回了正确的机场名称,但它有两个缺点。它仅在您使用大写字母搜索时才有效。所以barcelona 不会返回任何东西,但Barcelona 会。

第二个缺点是只有当值完全等于机场名称时才会返回。

如何根据部分搜索返回值?所以Bar 而不是Barcelona,我该如何解决资金问题?

【问题讨论】:

  • 如果有多个以 Bar 开头的匹配项怎么办?
  • 那么它应该返回所有包含Bar的结果。因此,用户只需键入即可获得更具体的结果。
  • Compare part of string的可能重复
  • @Caramiriel:虽然有一些重叠,但我不会称之为重复。如果没有别的,这增加了过滤列表的整个问题。

标签: javascript angular


【解决方案1】:

我会尝试这样的:

const findMatches = (values) => test => {
  const regex = new RegExp(test, 'i'); 
  return values.filter(val => regex.test(val.name))
}

const searchAirports = findMatches(airports);

显然你可以内联findMatches 函数,但我认为这样更易读。

【讨论】:

    【解决方案2】:

    忽略案例:

    value.toLowerCase() === i.name.toLowerCase()

    对于部分搜索,您可能需要使用正则表达式 (Regex)

    【讨论】:

      【解决方案3】:

      您可以通过以下方式使用正则表达式

      let arr = ['abc', 'abd', 'Abe', 'bcd', 'cde', 'edf'];
      
      let input = 'ab';
      let re = new RegExp('^' + input, 'i');
      
      let result = arr.filter(e => e.match(re) != null);
      
      console.log(result);

      【讨论】:

      • 当我使用你的数组时它工作正常,但是当我使用我的数组时我得到ERROR TypeError: e.match is not a function。我数组中的对象看起来像这样{id: "100", name: "Ottawa Macdonald Cartier Intl", iata: "YOW", icao: "CYOW", lon: "-75.669167", …
      • 试试 e.name.match()
      • 相比e.match(re) != null(有或没有name 属性),您是否认为re.test(e.name) 似乎是filter 的更好选择?
      【解决方案4】:

      你可以这样做:

      performFilter(filterBy: string): IProduct[] {
          filterBy = filterBy.toLocaleLowerCase();
          return this.products.filter((product: IProduct) =>
                product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
      }
      

      这将执行不区分大小写的过滤器,并将返回包含任何已定义文本的所有项目。

      【讨论】:

        【解决方案5】:

        在前端搜索大量数据,这是我在javascript端做的-

        1. 假设您的数据数组(JSON 对象)看起来像 ['abcd', 'abfer', 'xyds', 'irkd',...](超过 10,0000 个元素)-array1

        2. 从 json 加载数组时,创建一个 javascript 数组,它是一个 26 长度的二维数组,并在每个索引处存储每个字符的元素索引。例如,对于上述数组,您的新数组如下所示 -[[0, 1], [0, 1], [0], [0, 2, 3], [1], [1], [], [], ...] - array2 含义 - char 'a' 存在于第 0 个元素和第 1 个元素中,char 'd' 存在于 0、2、3 元素中。

          现在您的对象已准备就绪,页面已准备好进行快速搜索。

        当用户键入搜索字符串时,onkeyup 你会这样做 -

        1. 假设用户搜索'bf'

        2. 从步骤 2 中的数组中,加载 char b 和 char f 的数组,并取两者的交集。您现在将拥有所有具有 char b 和 char f - intersected 的元素的位置

        3. 现在您遍历交集数组,直接访问原始数组中的那些索引(从步骤 1 开始),然后执行 indexOf('bf')

          //pseudo code var t = 0; $.each(intersected, function(k, v){ if(array1[k].indexOf(searchString) > -1){ results[t++] = array1[k]; } }); return results;

        这样您就不会遍历数组中的所有元素。您只迭代将有字符用户搜索的元素。

        要提供不区分大小写的搜索,请在准备 array2 和搜索时转换所有 toLowerCase()

        【讨论】:

          【解决方案6】:

          检查下面的示例代码。可能对你有帮助。

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

          【讨论】:

            猜你喜欢
            • 2023-02-11
            • 2020-09-26
            • 1970-01-01
            • 1970-01-01
            • 2022-11-27
            • 1970-01-01
            • 2021-08-27
            • 2012-11-15
            相关资源
            最近更新 更多