制作自己的Search Suggest 1-拼音切分
什么是Search Suggest(搜索建议),上一个截图大家就知道:

对,就是一个输入提示,问了很多人,都以为我是说前台ajax的实现问题。因为很多人都觉得后台数据只要一个select就可以得到……但真的是一个select就可以得到吗?我想了好久都没想到这条select怎么写,于是开始自己琢磨。
我所想到的首先要做的是将输入的东西拆分。比如sg要拆分为[s,g],sog要拆分为[so,g],soug=>[sou,g],sougou => [sou,gou]等等……,当然了,有一些拼音很难拆,比如xian这样的,我的做法是对于这种拼音在拆分环节不进行拆分,即:xian => [xian]。
首先要找到一份字库,我在网上下了一份:

字库对提示的影响很大,好的字库能提高很大效率。载入字库很简单,就是Properties的load,我要说的是载入字库后要进行的一些操作:
载入字库后首先要对字库所有的拼音进行分析,将其分析成一棵树:
如
a
-i
--n
?---g
-o
-n
这样才能对用户输入的拼音进行分析。
这是我的代码:
for (Iterator it = ziku.keySet().iterator(); it.hasNext();) {String key = (String) it.next();char ch = key.charAt(0);PinyinCharNode root = roots.get(ch);if (root == null) {root = PinyinCharNode.valueOf(ch);roots.put(ch, root);}PinyinCharNode node = root;for (int i = 1; i < key.length(); i++) {ch = key.charAt(i);PinyinCharNode tempNode = node.getNodeByChar(ch);if (tempNode == null) {node = node.addNode(ch);} else {node = tempNode;}}}?注释:roots是一个Map类型的对象,保存所有的根节点
下一步工作就是分析用户输入的过程。
1、优先对隔音符进行切分
2、逐个字符进行分析,在第一个字符时获取roots里的数据,如果获取不到,则该这个音符不是声母或a,o,e开头的韵母(a,o,e开头的韵母可以作为单独音节)
3、如果获得root,再分析下一个字符是否为root的子节点。循环下去,直到某个节点,那个节点的下一个字符在这个节点的子节点内无法找到,这时下一个节点作为下一个音节的开始字符
4、循环,直到完成整个字符串
public static List<String> splitPinyin(String pinyin) {String[] pinyins = pinyin.split("'");// 优先使用隔音符List<String> resultPinyins = new ArrayList<String>();for (String s : pinyins) {int index = 0;PinyinCharNode node = roots.get(s.charAt(index));StringBuffer notPinyin = new StringBuffer();while (index < s.length() && node == null) {notPinyin.append(s.charAt(index));index++;if (index < s.length())node = roots.get(s.charAt(index));}if (notPinyin.length() > 0) {resultPinyins.add(notPinyin.toString());notPinyin = new StringBuffer();}if (index == s.length()) {return resultPinyins;}StringBuffer bufPinyin = new StringBuffer();bufPinyin.append(s.charAt(index));if (index == s.length() - 1) {resultPinyins.add(bufPinyin.toString());}for (int i = index + 1; i < s.length(); i++) {if (!Character.isLetter(s.charAt(i))) {// 如果不是字母if (bufPinyin.length() > 0) {resultPinyins.add(bufPinyin.toString());bufPinyin = new StringBuffer();}resultPinyins.add(String.valueOf(s.charAt(i)));continue;}PinyinCharNode tempNode = node.getNodeByChar(s.charAt(i));if (tempNode == null) {if (bufPinyin.length() > 0)resultPinyins.add(bufPinyin.toString());bufPinyin = new StringBuffer();bufPinyin.append(s.charAt(i));node = roots.get(s.charAt(i));if (i == s.length() - 1) {resultPinyins.add(bufPinyin.toString());}} else {bufPinyin.append(s.charAt(i));if (i == s.length() - 1) {resultPinyins.add(bufPinyin.toString());}node = tempNode;}}}return resultPinyins;}?这个方法我测试了几次,应该没有问题。
附PinyinCharNode.java代码:
public class PinyinCharNode {private PinyinCharNode() {super();}private char ch;private List<PinyinCharNode> nodes = Collections.synchronizedList(new ArrayList<PinyinCharNode>());public char getCh() {return ch;}public void setCh(char ch) {this.ch = ch;}public List<PinyinCharNode> getNodes() {return nodes;}public void setNodes(List<PinyinCharNode> nodes) {this.nodes = nodes;}public void addNode(PinyinCharNode node) {this.nodes.add(node);}public PinyinCharNode addNode(char node) {PinyinCharNode p = valueOf(node);addNode(p);return p;}public PinyinCharNode getNodeByChar(char ch) {for (PinyinCharNode node : nodes) {if (ch == node.getCh()) {return node;}}return null;}private PinyinCharNode(char ch) {super();this.ch = ch;}public static PinyinCharNode valueOf(char ch) {return new PinyinCharNode(ch);}}?PS:本人绝对是新手……本人也绝对是新手文……但属本人原创……高手请飘过……