每过一段时间,我的网站和论坛就会出现注册邮件错误问题。而且往往是缺少某个字符这样的错误。例如:hotmail.com写成了hotmai.com 对于这种意图明确但又不容易发现的错误,普通邮件格式验证函数是无法处理的。因为这种拼写错误依然属于合法邮件地址。但是一个友好的Web页面应该给与用户适当的提示。这里我提出一个容易想到的简单方法处理这个问题。
我们计算用户输入的邮件域和一些常见邮件域的 Levenshtein Distance,也称作字符串编辑距离,是指从一个字符串转换到另一个字符串最小的编辑操作次数。对于LD足够小但又不为0的情况,给于用户提示。
下面给出Levenshtein Distance的js实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
function levenshtein(a, b) { var i; var j; var cost; var d = new Array(); if (a.length == 0) { return b.length; } if (b.length == 0) { return a.length; } for (i = 0; i <= a.length; i++) { d[i] = new Array(); d[i][0] = i; } for (j = 0; j <= b.length; j++) { d[0][j] = j; } for (i = 1; i <= a.length; i++) { for (j = 1; j <= b.length; j++) { cost = (a.charAt(i - 1) == b.charAt(j - 1)) ? 0 : 1; d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); if (i > 1 && j > 1 && a.charAt(i - 1) == b.charAt(j - 2) && a.charAt(i - 2) == b.charAt(j - 1)) { d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost) } } } return d[a.length][b.length]; } |
接下来我们要准备一些常用的邮件域信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
function checkCommonMail(id,errorid) { var email = document.getElementById(id).value; var useremailDomain=email.substring(email.indexOf("@")+1).toLowerCase(); var error=document.getElementById(errorid); var commonDomain = [ "hotmail.com", "gmail.com", ["yahoo.cn","yahoo.hk","yahoo.com.cn","yahoo.com.hk","yahoo.com"], "163.com", "sina.com", "live.com", "qq.com", "vip.qq.com"]; for(var i=0;i<commonDomain.length;i++){ if (commonDomain[i] instanceof Array) { var pardomain=commonDomain[i]; var dis=new Array(); for(var j=0;j<pardomain.length;j++){ dis[j]=levenshtein(useremailDomain,pardomain[j]); } var mindis=100000,minj=0; for(var j=0;j<dis.length;j++){ if(dis[j]==0) return; if(dis[j]<mindis) { mindis=dis[j]; minj=j; } } if(mindis==0) return; if(mindis<3){ error.innerHTML = '您的邮件地址很像'+pardomain[minj]+'?'; } delete dis; return; }else{ var dis=levenshtein(useremailDomain,commonDomain[i]); if(dis==0) return; if(dis<2){ error.innerHTML = '您的邮件地址很像'+commonDomain[i]+'?'; return; } delete dis; } } } |
上面的函数中yahoo域为并列结算,这样计算更符合用户的意图。
该方式适用处理用户无意间输入的错误。当然你可以同时配合邮箱格式验证函数,来过滤掉一些完全错误的邮箱输入:
1 2 3 4 5 6 7 8 9 |
function checkMail(id) { var email = document.getElementById(id).value; var pattern = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; if (pattern.test(email)) { return true; } else { return false; } } |
最后加一句题外话。作为一个普通的程序员,应该能够合理的应用上述功能函数。但是作为一个优秀的程序员,应该能理解上述函数算法。通过阅读上面levenshtein函数,优秀的程序员应该立即识别出这是一个典型的动态规划算法,哪里是动态转移方程,时间复杂度大概是什么等等。