我也修改了 jQuery Autocomplete 实现以生成自动更正建议。我使用 Levenshtein 距离作为衡量最接近匹配的指标。
在 jQuery 自动完成没有更多建议之后,我的代码在每次按键时运行。这是我写的代码:
// Returns edit distance between two strings
edit_distance : function(s1, s2) {
// Auxiliary 2D array
var arr = new Array(s1.length+1);
for(var i=0 ; i<s1.length+1 ; i++)
arr[i] = new Array(s2.length+1);
// Algorithm
for(var i=0 ; i<=s1.length ; i++)
for(var j=0 ; j<=s2.length ; j++)
arr[i][j] = 0;
for(var i=0 ; i<=s1.length ; i++)
arr[i][0] = i;
for(var i=0 ; i<=s2.length ; i++)
arr[0][i] = i;
for(var i=1 ; i<=s1.length ; i++)
for(var j=1 ; j<=s2.length ; j++)
arr[i][j] = Math.min(arr[i-1][j-1] + (s1.charAt(i-1)==s2.charAt(j-1) ? 0 : 1), arr[i-1][j]+1, arr[i][j-1]+1);
// Final answer
return arr[s1.length][s2.length].toString(10);
},
// This is called at each keypress
auto_correct : function() {
// Make object array for sorting both names and IDs in one go
var objArray = new Array();
for(var i=0 ; i<idArray.length ; i++) {
objArray[i] = new Object();
objArray[i].id = idArray[i];
objArray[i].name = nameArray[i];
}
// Sort object array by edit distance
var out = this;
companyObjArray.sort (
function(a,b) {
var input = jQuery("#inputbox").val().toLowerCase();
var d1 = a.name.toLowerCase();
var d2 = b.name.toLowerCase();
return out.editDistance(input,d1) - out.editDistance(input,d2);
}
);
// Copy some closest matches in arrays that are shown by jQuery
this.suggestions = new Array();
this.data = new Array();
for(var i=0 ; i<5 ; i++) {
this.suggestions.push(companyObjArray[i].name);
this.data.push(companyObjArray[i].id);
}
}
所有名称都有与之关联的 ID,因此在排序之前,我只是从中创建一个对象数组,并对数组进行排序。
由于要搜索的列表有数千个,因此速度很慢。我发现了一个叫做 BK-tree 的数据结构,它可以加快速度,但我现在无法实现它。我正在寻找优化建议以加快速度。欢迎任何建议。提前致谢。
编辑。我决定使用Sift3作为我的字符串距离度量而不是 Levenshein 距离,它可以提供更有意义的结果并且速度更快。