簡單的說,編輯距離就是把一個字串修改變成另一個字串的修改次數。如果修改的次數越小,我們可以簡單的認為這兩個字串之間的關係越緊密。比如 今天是星期幾 對於 今天是星期五 和 明天是星期五比較,跟 今天是星期五 更加緊密一些,因為前者的編輯距離是 1,後者的編輯距離是 2。
更詳細的百度百科已經說的很清楚了,這裡不再贅述,主要給出 JavaScript 的實現方法:
按照自然語言表達的演算法,我們先需要根據兩個字串的長度建立一個二維表:
function levenshtein(a, b) { var al = a.length + 1; var bl = b.length + 1; var result = []; var temp = 0; // 建立一個二維數組 for (var i = 0; i < al; result[i] = [i++]) {} for (var i = 0; i < bl; result[0][i] = i++) {}}
之後就需要遍曆這個二位元組,按照如下的規則取得三個值的最小值:
如果最上方的字元等於最左方的字元,則為左上方的數字。否則為左上方的數字 + 1。
左方數字 + 1
上方數字 + 1
需要判斷兩個值是否相等來決定左上方數字是否 + 1,所以引入 temp 變數。我們可以寫出如下遍曆代碼:
for (i = 1; i < al; i++) { for (var j = 1; j < bl; j++) { // 判斷最上方和最左方數字是否相等 temp = a[i - 1] == b[j - 1] ? 0 : 1; // result[i - 1][j] + 1 左方數字 // result[i][j - 1] + 1 上方數字 // result[i - 1][j - 1] + temp 左上方數字 result[i][j] = Math.min(result[i - 1][j] + 1, result[i][j - 1] + 1, result[i - 1][j - 1] + temp); }}
最後將二維數組最後一個值返回,該值就是編輯距離:
return result[i-1][j-1];
這個函數就完成了:
function levenshtein(a, b) { var al = a.length + 1; var bl = b.length + 1; var result = []; var temp = 0; // 建立一個二維數組 for (var i = 0; i < al; result[i] = [i++]) {} for (var i = 0; i < bl; result[0][i] = i++) {} for (i = 1; i < al; i++) { for (var j = 1; j < bl; j++) { // 判斷最上方和最左方數字是否相等 temp = a[i - 1] == b[j - 1] ? 0 : 1; // result[i - 1][j] + 1 左方數字 // result[i][j - 1] + 1 上方數字 // result[i - 1][j - 1] + temp 左上方數字 result[i][j] = Math.min(result[i - 1][j] + 1, result[i][j - 1] + 1, result[i - 1][j - 1] + temp); } } return result[i-1][j-1]; }
實際應用
那麼我們現在就來實現一個簡單的搜尋功能。
大體思路就是將資料與要搜尋的字串計算編輯距離,然後進行排序,將編輯距離小的放在上面顯示。具體 Demo 做在
看個小編寫的例子
<html><head><title>Javascript模糊尋找</title></head><body><li onload="load('Name')" id="name">Name</li><li onload="load('sex')" id="sex">sex</li><li onload="load('age')" id="age">age</li><li onload="load('job')" id="job">job</li><li onload="load('mail')" id="mail">E-mail</li><input id="input" type="text" value="" /><input id="search" type="button" onclick="findEach()" value="Search" /><script>var vData= ["name", "sex", "age", "job", "E-mail"];function load(id){alert(vData[0]);//vData[vData.length] = document.getElementById(id).innerHTML;}function find(sFind, sObj){var nSize = sFind.length;var nLen = sObj.length;var sCompare;if(nSize <= nLen ){for(var i = 0; i <= nLen - nSize; i++){sCompare = sObj.substring(i, i + nSize);if(sCompare == sFind){return i;}}}return -1;}function findEach(){var sFind = document.getElementById("input").value;if(sFind==""){alert("Can not be empty");}if(sFind!=""){var nPos;var vResult = [];//for(var i = 0; i <= vData.length; i++){for(var i in vData){//nPos = find(sFind, vData[i]);var sTxt=vData[i]||'';nPos=sTxt.indexOf(sFind);if(nPos>=0){vResult[vResult.length] = sTxt;}}alert(vResult);}}</script></body></html>