【问题标题】:Fuzzy searching using regex使用正则表达式进行模糊搜索
【发布时间】:2019-02-18 07:30:59
【问题描述】:

我有一个对象,其键为要搜索的某个名称并评估其分数,如下所示:

{

   'a': 344,
   'apple': 345354,
   'orange': 320,
   'mango': 39999,
   .
   .
   .
}

地图有大约 50 万个键。我需要做一个模糊搜索来为ornge之类的一些文本创建一个测试自动建议功能(支持拼写错误),它应该匹配orange,并返回所有匹配的单词。此外,匹配可以出现在字符串中的任何位置,而不仅仅是在开头。我怎么能用正则表达式做到这一点?我正在尝试以下方法:

(?=.*\ornge\b).*

但它不起作用。我怎么能这样做?

使用regex 可能不是最佳解决方案。您能建议一种替代方法吗?

【问题讨论】:

  • 可能是o.*r.*n.*g.*e?
  • 恕我直言,您不应该尝试在正则表达式中执行此操作。
  • @appleapple 好的。你能推荐一个方法吗?
  • 您应该找到一个库来执行此操作,或者至少您需要更清楚地定义您想要匹配的内容(以便实际实现它)。我对此不太熟悉,所以我只能建议。
  • 有多种模糊搜索算法。您可以在搜索中引入某种通配符(例如*),或者您可以对输入进行有效排列。在后一种情况下,您需要实现近似字符串匹配算法。有一些建议here.

标签: javascript regex


【解决方案1】:

对于文本输入inputVal 和您的对象obj。:

let regexString = '';
inputVal.split('').forEach(char => regexString += char + '.*');
const rgx = new RegExp(regexString, 'i');
const result = Object.keys(obj).filter(key => key.match(rgx));

【讨论】:

    【解决方案2】:

    使用正则表达式不会那么简单。我同意@apple apple 的观点,即寻找图书馆是有意义的。我很想知道手动删除一个基本的需要多长时间,所以我做了这个,随意使用/改进它以优化处理你拥有的更大的列表。

    基本要点是您设置输入和预期输出之间长度相似度的阈值,以及您想要达到的最小字母匹配分数。

    对于集合中的每个单词,您在该单词和输入之间运行一个比较函数。在比较函数中,您针对单词测试输入的每个字母以查看它是否存在 - 如果存在,则从单词中删除该字母并移动到下一个(以避免从多个匹配到同一个字母夸大分数:即如果a 在第一场比赛后没有被删除,则字符串aaaaaaapple 的得分为6)

    如果您想启用多个建议,您可以将while(++i < listlen) 循环替换为wordlist.filter,并返回所有高于某个分数阈值的单词。

    const wordlist = ["apple", "orange", "mango", "fruit", "banana", "kiwi", "grapefruit"],
      listlen = wordlist.length,
      wordLengthDifferential = 1,
      scoreDifferential = 3
    
    function compare(str, word){
      let score = 0
      str = str.split('')
      word = word.split('')
      while(str.length){
        let idx = word.indexOf(str.pop())
        if(idx > -1){
          ++score
          word.splice(idx, 1)
        }
      }
      return score
    }
    
    function getSuggestion(str){
      let highScore = 0, suggestion = null, i = -1
      
      while(++i < listlen){
        let word = wordlist[i]
        if(Math.abs(word.length - str.length) <= wordLengthDifferential) {
          let score = compare(str, word)
          console.log(str, word, score)
          if(score > highScore && score >= scoreDifferential){
          	suggestion = word
            highScore = score
          } 
        }
      }  
      
      return suggestion || "no relevant matches"
    }
    
    document.querySelector('button').onclick = e => console.log(getSuggestion(document.querySelector('input').value))
    document.addEventListener('keydown', e => {
    	if(e.keyCode == 13) console.log(getSuggestion(document.querySelector('input').value))
    })
    &lt;input type="text" /&gt;&lt;button&gt;Go&lt;/button&gt;&lt;em&gt;(or press enter)&lt;/em&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 2016-07-19
      相关资源
      最近更新 更多