19

Javascript を使用して、2 つの文字列の間にいくつの違いがあるかを確認したいと考えています。

何かのようなもの:

var oldName = "Alec";
var newName = "Alexander";
var differences = getDifference(oldName, newName) // differences = 6
  • 名前に追加された文字は、文字ごとに 1 つの変更としてカウントする必要があります。
  • 文字の変更は、文字ごとの変更としてカウントされます。2つを交換する
  • 文字は、実際に各文字を変更するため、2 つの変更としてカウントする必要があります
  • ただし、文字をずらして別の文字を挿入することは、1 回の変更としてカウントする必要があります。

例えば:

「Alex」を「Alexander」に変更すると、5 文字が追加されるため、5 つの変更になります。

「アレックス」を「アレックス」に変更することは、「l」を追加して残りをシフトしたが変更しなかったため、1つの変更にすぎません

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

しかし、変更としてカウントされない文字のシフトをどのように説明できますか?


更新:これが私がそれを機能させた方法です

レーベンシュタイン距離はまさに私が必要としていたものでした。ピーターに感謝!

ワーキング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 の功績によるものです。

この機能を示すジェームズの投稿

4

2 に答える 2

13

私は Javascript の実装自体を手元に持っていませんが、確立されたアルゴリズムが存在する何かを行っています。具体的には、2 つの文字列間の「レーベンシュタイン距離」、つまり挿入、置換、および削除の数を探していると思います (削除を変更として扱っている場合)。

レーベンシュタイン距離のウィキペディアのページには、開始できるさまざまな疑似コードの実装と、役立つ参考文献があります。

于 2013-08-05T05:41:18.443 に答える