javascript 用Javascript检测两个字符串之间的差异
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18050932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
detect differences between two strings with Javascript
提问by Wesley Smith
With Javascript, I want to check how many differences there are between two strings.
使用 Javascript,我想检查两个字符串之间有多少差异。
Something like:
就像是:
var oldName = "Alec";
var newName = "Alexander";
var differences = getDifference(oldName, newName) // differences = 6
- Any letters added to the name should count as one change per letter.
- Changing a letter should count as a change per letter. Swaping two
- letters should count as two changes as your really changing each
leter. - However, shifting a letter and inserting another should only count as one change.
- 添加到名称中的任何字母都应计为每个字母的一次更改。
- 更改一个字母应该算作每个字母的更改。交换两个
- 字母应该算作两次更改,因为您真正更改了每个
字母。 - 但是,移动一个字母并插入另一个字母只能算作一次更改。
For example:
例如:
Changing "Alex" to "Alexander" would be 5 changes as 5 letters have been added
将“亚历克斯”更改为“亚历山大”将是 5 次更改,因为已添加 5 个字母
Changing "Alex" to "Allex" would only be one change as you added an "l" and shifted the rest over but didnt change them
将“亚历克斯”更改为“亚历克斯”只会是一个更改,因为您添加了“l”并将其余部分移过来但没有更改它们
Changing "Alexander" to "Allesander"would be 2 changes (adding the "l" and changing "x" to a "s").
将“Alexander”更改为“Allesander”将是 2 个更改(添加“l”并将“x”更改为“s”)。
I can split each name into an array of letters and compare them easy enough like in this jsFiddlewith the below function:
我可以将每个名称拆分为一个字母数组,并像在此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);
}
But how can I account for the shifting of letters not counting as a change?
但是我怎么能解释信件的变化不算是变化呢?
Update: Here's how I got it working
更新:这是我的工作方式
Levenshtein distancewas exactly what I needed. Thanks to Peter!
Levenshtein 距离正是我所需要的。感谢彼得!
$(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>
Credit to James Westgate for the function:
归功于 James Westgate 的功能:
采纳答案by Peter
I don't have a Javascript implementation on hand per se, but you're doing something for which well-established algorithms exist. Specifically, I believe you're looking for the "Levenshtein distance" between two strings -- i.e. the number of insertions, substitutions and deletions (assuming you are treating a deletion as a change).
我手头没有 Javascript 实现本身,但您正在做一些存在完善算法的事情。具体来说,我相信您正在寻找两个字符串之间的“Levenshtein 距离”——即插入、替换和删除的数量(假设您将删除视为更改)。
The wikipedia page for Levenshtein distancehas various pseudo-code implementations from which you could start, and references which may also help you.
Levenshtein distance 的维基百科页面有各种伪代码实现,您可以从中开始,参考也可能对您有所帮助。
回答by ClojureMostly
/**
* 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];
};