Soundex 算法是一种拼音算法,用于按英语发音来索引姓名,它最初由美国人口调查局开发。
Soundex 方法返回一个表示姓名的四字符代码,由一个英文字母后跟三个数字构成。
字母是姓名的首字母,数字对姓名中剩余的辅音字母编码。 发音相近的姓名具有相同的 SoundEx 代码。
辅音字母将映射到一个特定的数字。
算法简要说明
1、将英文字按以下规则替换(除第一个字符外):
a e h i o u w y -> 0
b f p v -> 1
c g j k q s x z -> 2
d t -> 3
l -> 4
m n -> 5
r -> 6
2、去除0,对于重复的字符只保留一个
3、返回前4个字符,不足4位以0补足
import java.util.*;
import java.lang.System.*;
public class Soundex {
private static final long serialVersion = 1L;
/*实现26个英文字母的映射*/
public static final char[] MAP = {
//A B C D E F G H I J K L M
'0','1','2','3','0','1','2','0','0','2','2','4','5',
//N O P Q R S T U V W X Y Z
'5','0','1','2','6','2','3','0','1','0','2','0','2'
};
public static void main(String args[]) {
List<String> names = new ArrayList<>();
names.add("songzhaoherng");
names.add("sonzhaoheng");
names.add("sungzhaoheng");
names.add("sunzhaoheng");
for(String name: names) {
System.out.println(Soundex.soundex(name) + "---->" + name);
}
}
/*将传过来的字符串转换为 Soundex 码
*不能转换的返回null
* */
public static String soundex(String s) {
String t = s.toUpperCase();//将其转换为大写(实现英文字母的统一)
StringBuffer sbu = new StringBuffer(); //StringBuffer更加安全
char c;
char prev = '?', PrevOutput = '?';//符号字符
/*主循环,找出映射的字符(最多4个)
* 算法仅能处理 ASCII 码,不要用Character.isLetter()
* */
for(int i = 0; i < t.length() && sbu.length() < 4 && (c = t.charAt(i)) != ','; i++) {
//判断字母是否为大写,且是否为符号字符
if(c >= 'A' && c <= 'Z' && c!= prev) {
prev = c;
//沿用首字符,依次进行排序,不是首字符的按照 Soundex 码
if(i == 0) {
sbu.append(c);
}else {
char m = MAP[c - 'A'];
/*
if(false) {
System.out.println(c + "---->" + m);
}*/
//去除重复的英文字母
if(m != '0' && m != PrevOutput) {
sbu.append(m);
PrevOutput = m;
}
}
}
}
//不能转换的返回null
if(sbu.length() == 0) {
return null;
}
//如果长度不够4就添加0
for(int i = sbu.length(); i < 4; i++) {
sbu.append('0');
}
return sbu.toString();
}
}
运行结果:
S526---->songzhaoherng
S525---->sonzhaoheng
S525---->sungzhaoheng
S525---->sunzhaoheng