摘要:谈谈我做拼音搜索的一点经验需要注意的一些事情本文使用的为语言解决方案。当然也我们可以自己实现转换拼音的功能,如果这样做,则需要在代码中设定好中文字库和对应的拼音,同时特别注意多音字的处理。
谈谈我做拼音搜索的一点经验 需要注意的一些事情
本文使用的为 Java 语言解决方案。
搜索方法上,按照个人理解,有两点关键:
分词
将类似 "women" 这样的词分解成 "wo"men"。经过这样的分词,在搜索时无论通过全拼音匹配,还是首字母匹配,处理起来都比较方便。
词库构建
目前我接触过的常见搜索场景有两种,它们对词库的建立有如下影响:
通讯录搜索
对词库有频繁的添加 / 删除操作。
站内搜索
使用预先维护好的词库。
实现如果是通讯录搜索,可以在新建联系人的时候,把联系人的名字转为拼音,存入数据库中另一个记录拼音的字段,在搜索的时候通过拼音来匹配。
如果是站内搜索,可以直接建立拼音词库,搜索的时候通过拼音来匹配。
首先是词库的构建。毫无疑问,我们需要为词库建一张至少包含中文词汇以及对应的拼音词汇的表。
通讯录搜索,可能会使用一些例如 pinyin4j 的第三方库,将中文字转换为拼音。当然也我们可以自己实现转换拼音的功能,如果这样做,则需要在代码中设定好中文字库和对应的拼音,同时特别注意多音字的处理。
下面是使用 pinyin4j 库的例子。使用 pinyin4j 库可以支持简体 / 繁体中文转换为拼音,而且支持带声调的格式化输出。
我们使用 Maven 来添加 pinyin4j,在 pom.xml 中添加
com.belerweb pinyin4j 2.5.0
实现类:
public class Chinese { private HanyuPinyinOutputFormat format = null; private String[] pinyin; public Chinese() { format = new HanyuPinyinOutputFormat(); format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); pinyin = null; } //转换单个中文字符 public String getCharacterPinYin(char c) { try { pinyin = PinyinHelper.toHanyuPinyinStringArray(c, format); } catch(BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } // 如果c不是汉字,返回null if(null == pinyin) return null; // 多音字取第一个值 return pinyin[0]; } //转换一个字符串 public String getStringPinYin(String str) { StringBuilder sb = new StringBuilder(); for(int i = 0; i < str.length(); ++i) { String tmp = getCharacterPinYin(str.charAt(i)); if(null == tmp) { // 如果str.charAt(i)不是汉字,则保持原样 sb.append(str.charAt(i)); } else { sb.append(tmp); //分词 if ( i < str.length() - 1 && null != getCharacterPinYin(str.charAt(i + 1))) { sb.append("""); } } } return sb.toString().trim(); } public static void main(String[] args) { Chinese chinese = new Chinese(); String str = "哈哈,我爱 Coding"; String pinYin = chinese.getStringPinYin(str); System.out.println(pinYin); } }
输出的结果
ha"ha,wo"ai Coding
每当有通讯录联系人更新时,采用上述方法更新数据库中的拼音字段即可。
站内搜索,词库来源可以使用搜狗标准词库和细胞词库等。
搜狗标准词库
下载的搜狗词库可以使用深蓝词库转换器来转换成 txt 文件,或者其他输入法的标准格式。
深蓝词库转换 2.0
转换为 txt 文件后,处理以后,修改成为 insert 语句,插入数据库。
最后的关键,就是将输入的拼音分词,然后与数据库中的拼音字段匹配,分词采用正则表达式实现。
分词实现:
public class PinyinUtils { //分词正则表达式 public static String regEx = "[^aoeiuv]?h?[iuv]?(ai|ei|ao|ou|er|ang?|eng?|ong|a|o|e|i|u|ng|n)?"; public static String split(String input) { int tag = 0; StringBuffer sb = new StringBuffer(); String formatted = ""; ListtokenResult = new ArrayList (); for (int i = input.length(); i > 0; i = i - tag) { Pattern pat = Pattern.compile(regEx); Matcher matcher = pat.matcher(input); boolean rs = matcher.find(); sb.append(matcher.group()); sb.append("""); tag = matcher.end() - matcher.start(); tokenResult.add(input.substring(0, 1)); input = input.substring(tag); } if (sb.length() > 0) { formatted = sb.toString().substring(0, sb.toString().length() - 1); } return formatted; } public static void main(String[] args) { String str = "koudingboke"; System.out.println(PinyinUtils.split(str)); } }
输出结果
kou"ding"bo"ke
根据此输出结果,在词库中匹配即可。
根据以上方式搜索出的词汇,会比较固定。如果有按照搜索频率对搜索结果排序的需求,可以针对每个词汇的查询计数。具体实现这里不再赘述。
个人一点粗浅经验,欢迎各位大牛一起交流。
参考来源怎样对拼音进行切分?
Brook Zhao
本文来自 Coding 官方技术博客,如需转载请注明出处,谢谢。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/64251.html
摘要:而且,据说他的大女儿和小女儿都是做测试的,这是名副其实的测试世家。确定测试需求相应的测试方法获得测试策略方案。负责这一领域测试质量保证开发内的整个开发生存周期业务。 ...
摘要:软件测试自学秘诀面试失败一天,心态稳的一批,因为面试的全是外包人事帮我联系的公司,工资全都是一万以上,之前只有四五千的自己根本不觉得自己能胜任。 个人是去年年底零基础转行,两三千培训费学出来,学完后也是稀里糊涂,仅是知道功能测试就是找问题,其他接口,性能,数据库,python基础,虚拟机搭建网站都实现了课程展示那样。面试资...
摘要:最近看到知乎上面很多讨伐培训班的问答文章,不禁想到了我和新手同事合作的一些经历其实你是培训班出来还是计算机科班毕业,没人在乎,关键是你表现出来的一些问题切切实实的对你的同事或合作伙伴造成了很大困扰,而且这些问题集中在某一部分人身上显露出来, 最近看到知乎上面很多讨伐培训班的问答、文章,不禁想到了我和新手同事合作的一些经历; 其实你是培训班出来还是计算机科班毕业,没人在乎,关键是你表...
摘要:最近看到知乎上面很多讨伐培训班的问答文章,不禁想到了我和新手同事合作的一些经历其实你是培训班出来还是计算机科班毕业,没人在乎,关键是你表现出来的一些问题切切实实的对你的同事或合作伙伴造成了很大困扰,而且这些问题集中在某一部分人身上显露出来, 最近看到知乎上面很多讨伐培训班的问答、文章,不禁想到了我和新手同事合作的一些经历; 其实你是培训班出来还是计算机科班毕业,没人在乎,关键是你表...
阅读 3135·2021-09-30 09:47
阅读 1962·2021-09-22 16:04
阅读 2236·2021-09-22 15:44
阅读 2516·2021-08-25 09:38
阅读 522·2019-08-26 13:23
阅读 1202·2019-08-26 12:20
阅读 2790·2019-08-26 11:59
阅读 1038·2019-08-23 18:40