【问题标题】:detect differences between two strings with Javascript使用 Javascript 检测两个字符串之间的差异
【发布时间】:2013-08-05 17:36:01
【问题描述】:

使用 Javascript,我想检查两个字符串之间有多少差异。

类似:

var oldName = "Alec";
var newName = "Alexander";
var differences = getDifference(oldName, newName) // differences = 6
  • 添加到名称中的任何字母都应计为每个字母一个变化。
  • 更改字母应计为每个字母的更改。交换两个
  • 字母应该算作两次更改,因为您确实在更改每个字母
    信。
  • 但是,移动一个字母并插入另一个字母只能算作一次更改。

例如:

将“Alex”更改为“Alexander”将进行 5 次更改,因为添加了 5 个字母

将“Alex”更改为“Allex”只是一个更改,因为您添加了一个“l”并将其余部分转移但没有更改它们

将“Alexander”更改为“Allesander”将进行 2 次更改(添加“l”并将“x”更改为“s”)。

我可以将每个名称拆分为一个字母数组,然后像在 jsFiddle 中一样使用以下函数轻松地比较它们:

function compareNames(){
    var oldName = $('#old').val().split("");
    var newName = $('#new').val().split("");
    var changeCount = 0;
    var testLength = 0;
    if(oldName.length > newName.length){
        testLength=oldName.length;    
    }
    else testLength=newName.length;
    for(var i=0;i<testLength;i++){
        if(oldName[i]!=newName[i]) {
           changeCount++;           
        }
    }
    alert(changeCount);
}

但我怎么能解释字母的移动不算作变化呢?


更新:这是我的工作原理

Levenshtein distance 正是我所需要的。感谢彼得!

Working jsFiddle

$(function () {
    $('#compare').click(function () {
        var oldName = $('.compare:eq(0)').val();
        var newName = $('.compare:eq(1)').val();
        var count = levDist(oldName, newName);
        $('#display').html('There are ' + count + ' differences present');
    });
});

function levDist(s, t) {
    var d = []; //2d matrix

    // Step 1
    var n = s.length;
    var m = t.length;

    if (n == 0) return m;
    if (m == 0) return n;

    //Create an array of arrays in javascript (a descending loop is quicker)
    for (var i = n; i >= 0; i--) d[i] = [];

    // Step 2
    for (var i = n; i >= 0; i--) d[i][0] = i;
    for (var j = m; j >= 0; j--) d[0][j] = j;

    // Step 3
    for (var i = 1; i <= n; i++) {
        var s_i = s.charAt(i - 1);

        // Step 4
        for (var j = 1; j <= m; j++) {

            //Check the jagged ld total so far
            if (i == j && d[i][j] > 4) return n;

            var t_j = t.charAt(j - 1);
            var cost = (s_i == t_j) ? 0 : 1; // Step 5

            //Calculate the minimum
            var mi = d[i - 1][j] + 1;
            var b = d[i][j - 1] + 1;
            var c = d[i - 1][j - 1] + cost;

            if (b < mi) mi = b;
            if (c < mi) mi = c;

            d[i][j] = mi; // Step 6

            //Damerau transposition
            if (i > 1 && j > 1 && s_i == t.charAt(j - 2) && s.charAt(i - 2) == t_j) {
                d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
            }
        }
    }
    // Step 7
    return d[n][m];
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input type="button" id="compare" value="Compare" /><br><br>
<input type="text" id="old" class="compare" value="Alec" />
<input type="text" id="new" class="compare" value="Alexander" />
<br>
<br>
<span id="display"></span>

感谢 James Westgate 提供的功能:

Jame's post showing this function

【问题讨论】:

  • 如果减去字母会发生什么?那么例如“Alex”到“Ale”?
  • 是的,这也是一个改变
  • 这个问题确实需要多加注意,这太酷了。 @DelightedD0D,有两件事:1.您是从其他来源获得该功能还是您自己编写了代码? 2.我有使用权限吗?
  • @ChrisCirefice Nah,有点出乎我的意料,@JamesWestgate 按照我的理解编写了函数stackoverflow.com/a/11958496/1376624

标签: javascript string compare


【解决方案1】:

我手头上没有 Javascript 实现本身,但是您正在做一些存在完善算法的事情。具体来说,我相信您正在寻找两个字符串之间的“Levenshtein 距离”——即插入、替换和删除的数量(假设您将删除视为更改)。

The wikipedia page for Levenshtein distance 有各种伪代码实现,您可以从这些实现入手,参考资料也可能对您有所帮助。

【讨论】:

    【解决方案2】:

    Alternative implemenation:

    /**
     * Computes the Levenshtein edit distance between two strings.
     * @param {string} a
     * @param {string} b
     * @return {number} The edit distance between the two strings.
     */
    goog.string.editDistance = function(a, b) {
      var v0 = [];
      var v1 = [];
    
      if (a == b) {
        return 0;
      }
    
      if (!a.length || !b.length) {
        return Math.max(a.length, b.length);
      }
    
      for (var i = 0; i < b.length + 1; i++) {
        v0[i] = i;
      }
    
      for (var i = 0; i < a.length; i++) {
        v1[0] = i + 1;
    
        for (var j = 0; j < b.length; j++) {
          var cost = Number(a[i] != b[j]);
          // Cost for the substring is the minimum of adding one character, removing
          // one character, or a swap.
          v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);
        }
    
        for (var j = 0; j < v0.length; j++) {
          v0[j] = v1[j];
        }
      }
    
      return v1[b.length];
    };
    

    【讨论】:

    • 什么是goog
    • google 的闭包库。你可以删除goog.string
    猜你喜欢
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多