如何优化这种同步“模糊搜索”功能并将其转换为异步功能?

时间:2018-06-01 21:58:43

标签: javascript fuzzy-search

问题

我正在尝试在基于Node.js的项目中实现某种“模糊搜索”。

模糊搜索是一种即使字符串不完全匹配也会返回结果的搜索。

我在另一个stackoverflow thread中找到了这段代码。代码如下。

这很好,但问题是 - 它是同步的当它搜索大型数组时,它会减慢整个程序的速度。

问题

欢迎使用ES6方法。只需要在最新的Chrome中使用,因此任何JS方法都可以使用。

  • 是否有任何新的JS方法可以优化此功能?

  • 我做错了什么让它更慢?

  • 我可以将此函数转换为返回promise的异步函数吗?它会在搜索过程中停止冻结应用程序吗?

  • 你知道有没有更好的“模糊搜索”实现? (我找到了一个名为fuzzysort的模块,不能说它是否好得多,如果你输入"folder test"(错误的顺序)它就不会返回"test folder"所以它不是那么好)

代码

调用搜索功能

searchArray 是其搜索的路径数组,例如:["C:\\test", "C:\\file.txt"...](0.5-5百万路径)

searchQuery 是一个没有空格的字符串,例如:filetxt

search () {
  const fuzzySearch = this.fuzzySearch(this.searchQuery.toLowerCase(), this.searchArray) 
  let result = fuzzySearch.filter(element => element.relevance >= 0.3)
  // sort by relevance
  var sortedResults = result.sort((a, b) => parseFloat(b.relevance) - parseFloat(a.relevance)).map(item => item.name);

  this.searchResults = sortedResults
},

模糊搜索功能

fuzzySearch (searchQuery, searchArray) {
  const get_bigrams = function(string) {
  const s = string.toLowerCase();
  const v = new Array(s.length - 1);
  for (let i = 0, end = v.length; i <= end; i++) {
      v[i] = s.slice(i, i + 2);
  }
  return v;
  };

  const string_similarity = function(str1, str2) {
      if ((str1.length > 0) && (str2.length > 0)) {
          const pairs1 = get_bigrams(str1);
          const pairs2 = get_bigrams(str2);
          const union = pairs1.length + pairs2.length;
          let hit_count = 0;
          for (let x of Array.from(pairs1)) {
              for (let y of Array.from(pairs2)) {
                  if (x === y) {
                      hit_count++;
                  }
              }
          }
          if (hit_count > 0) {
              return ((2.0 * hit_count) / union);
          }
      }
      return 0.0;
  };

  let results = [];
  for (let name of searchArray) {
    // I added .match to use only the base filename (name+ext) not the whole path, and removed all characters
    let filteredPath = name.match(/[^\\\/]+$/)[0].replace(/[^A-Za-z0-9.]+/g, '')

    const relevance = string_similarity(searchQuery, filteredPath);
    const obj = {name, relevance};
    results.push(obj);
  }
  return results
},

0 个答案:

没有答案