制作自己的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:本人绝对是新手……本人也绝对是新手文……但属本人原创……高手请飘过……

你可能感兴趣的:(Ajax,工作)