【问题标题】:Determine if two strings are similar in Javascript?确定两个字符串在Javascript中是否相似?
【发布时间】:2011-04-25 12:34:31
【问题描述】:

假设我有两个字符串,有什么方法可以检查它们是否至少 90% 相似?

var string1 = "theBoardmeetstoday,tomorrow51";
var string2 = "Board meets today, tomorrow";

谢谢,

泰根

【问题讨论】:

    标签: javascript string logic


    【解决方案1】:

    Levenshtein distance 的维基百科条目包含一个示例实现。

    【讨论】:

    • 您能否通过此示例提供指向该页面确切修订版本的链接(以防该示例从页面中删除?)
    • 这里是页面的具体修改(从2010年10月14日开始):en.wikipedia.org/w/…
    【解决方案2】:

    jsdifflib 是 Python 优秀的 difflib 库的 JavaScript 端口。

    它有一个函数ratio(),它“返回[s]作为[0, 1]范围内的浮点数的序列相似性的度量。

    【讨论】:

      【解决方案3】:

      String.levenshtein(MooTools 插件)

      查看:http://mootools.net/forge/p/string_levenshtein

      GitHub:https://github.com/thinkphp/String.levenshtein

      此方法计算两个字符串之间的 Levenshtein 距离。在信息论和计算机科学中,Levenshtein 距离是衡量两个序列之间差异量(称为编辑距离)的度量。两个字符串之间的 Levenshtein 距离由将一个字符串转换为另一个给定字符串所需的最小操作数给出,其中可能的操作是插入、删除或替换单个字符。

      Levenshtein 距离算法已用于:

      • 拼写检查
      • 语音识别
      • DNA 分析
      • 抄袭检测

      【讨论】:

      【解决方案4】:

      还要考虑Dice's Coefficient,它被string-similarity github repo 及其对应的npm module 的创建者认为比Levenshtein 距离“基本上更好”。

      其文档中的用法:

      var stringSimilarity = require('string-similarity');
      
      var similarity = stringSimilarity.compareTwoStrings('healed', 'sealed'); 
      
      var matches = stringSimilarity.findBestMatch('healed', ['edward', 'sealed', 'theatre']);
      

      【讨论】:

        【解决方案5】:

        借鉴其他人的答案,我写了一个简单的js函数stringsAreSimilar来做到这一点:

        // https://github.com/thinkphp/String.levenshtein/blob/master/Source/String.levenshtein.js
        
        function getStringDifference(stringA, stringB) {
          var cost = [],
            str1 = stringA,
            str2 = stringB,
            n = str1.length,
            m = str2.length,
            i, j;
        
          var minimum = function (a, b, c) {
            var min = a;
            if (b < min) {
              min = b;
            }
            if (c < min) {
              min = c;
            }
            return min;
          };
        
          if (n == 0) {
            return;
          }
          if (m == 0) {
            return;
          }
        
          for (var i = 0; i <= n; i++) {
            cost[i] = [];
          }
        
          for (i = 0; i <= n; i++) {
            cost[i][0] = i;
          }
        
          for (j = 0; j <= m; j++) {
            cost[0][j] = j;
          }
        
          for (i = 1; i <= n; i++) {
        
            var x = str1.charAt(i - 1);
        
            for (j = 1; j <= m; j++) {
        
              var y = str2.charAt(j - 1);
        
              if (x == y) {
        
                cost[i][j] = cost[i - 1][j - 1];
        
              } else {
        
                cost[i][j] = 1 + minimum(cost[i - 1][j - 1], cost[i][j - 1], cost[i - 1][j]);
              }
        
            } //endfor
        
          } //endfor
        
          return cost[n][m];
        }
        
        function stringsAreSimilar(stringA, stringB) {
          var difference = getStringDifference(stringA, stringB);
          debugConsoleLog("stringA" + stringA);
          debugConsoleLog("stringB" + stringB);
          debugConsoleLog("difference" + difference);
          
          return difference < 10;
        }
        
        var string1 = "theBoardmeetstoday,tomorrow51";
        var string2 = "Board meets today, tomorrow";
        
        if(similar) {
            console.log("they are similar");
        } else {
            console.log("they are not similar");
        }
        
        
        

        【讨论】:

          【解决方案6】:

          所以我去年就尝试这样做。我读到Levenshtein distance 是 OP 在这里询问的解决方案。

          我从一个线程中看到了一个代码,但没有得到太多支持。也许是因为它的时间复杂性(在 forloop 中有一个 forloop)。我试过了,它似乎对我有用。该函数返回一个分数,其中 0 是一个很好的匹配,另一方面,更高的分数意味着偏离一个接近的匹配。生病分享,也许有人可以扩展它或更好地解释它:

          function editDistance(s1, s2) {
              s1 = s1.toLowerCase();
              s2 = s2.toLowerCase();
          
              var costs = new Array();
              for (var i = 0; i <= s1.length; i++) {
                  var lastValue = i;
                  for (var j = 0; j <= s2.length; j++) {
                      if (i == 0) costs[j] = j;
                      else {
                          if (j > 0) {
                              var newValue = costs[j - 1];
                              if (s1.charAt(i - 1) != s2.charAt(j - 1))
                                  newValue =
                                      Math.min(Math.min(newValue, lastValue), costs[j]) +
                                      1;
                              costs[j - 1] = lastValue;
                              lastValue = newValue;
                          }
                      }
                  }
                  if (i > 0) costs[s2.length] = lastValue;
              }
              return costs[s2.length];
          }

          祝你好运并分享您对此的想法 - 太棒了!干杯!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-09-18
            • 2015-10-17
            • 2010-10-22
            • 1970-01-01
            • 2022-12-03
            • 1970-01-01
            • 2016-05-02
            • 2020-10-05
            相关资源
            最近更新 更多