android T9 搜索联系人分析与实现(支持多音字)
来源:互联网 发布:网络营销策划岗位职责 编辑:程序博客网 时间:2024/04/25 05:30
最近在android项目开发过程中需要实现类似电话拨号功能,这里涉及到T9键盘搜索联系人,于是研究了一番,将思路和心得记录于此,方便自己与他人。
相信大家对T9输入法并不陌生,这里并不涉及到T9输入法,这里只涉及到T9搜索.以T9键盘搜索联系人为例,分析与实现T9搜索。
一开始我的想法是,根据T9键盘的输入然后组合起来,根据所有组合来进行搜索,但仔细一想,很显然行不通,这样组合起来的结果是随着输入字符的增加成指数级增长的.后来一想,T9键盘输入是'0'~'9','*',‘#’这12个字符的组合,为了更具通用性,应该将输入与搜索分开,搜索模块应该根据最原始的T9输入数据来匹配有限基本数据(这里是所有联系人),然后返回搜索结果.所以形成如下思路:
T9搜索联系人思路:
1.加载联系人(获取姓名与电话号码)
2.解析联系人(将可能含有汉字的字符串(姓名)解析成可直接根据输入可匹配的格式)
3.获得T9输入(获得‘0’~‘9’,‘*’,'#'组成的字符串)
4.根据T9输入数据匹配联系人 (根据获得‘0’~‘9’,‘*’,'#'组成的字符串,匹配解析后的联系人数据)
5.显示结果 (显示匹配结果)
T9搜索联系人基本上就是上述流程.1,3,5点实现起来问题不大,关键是2,4点,我们将重点主要放在2,4点上。
代码分析与实现
1.基本数据结构
(1)保存单个拼音的基本数据结构:T9PinyinUnit
public class T9PinyinUnit {private String mPinyin;//保存拼音串(当然也可以任意字符串)private String mNumber; //保存mPinyin对应的T9数字 ......}
例如:
"hao" => mPinyin="hao";mNumber="426";
"???hao" => mPinyin="???hao";mNumber="???426";
(2)保存单个汉字拼音(可能多音字)的基本数据结构
public class PinyinUnit {private boolean mPinyin;//判断是否是拼音(可能是汉字转换成的拼音,也可能是非汉字转换的字符串)private int mStartPosition;//记录此汉字或字符串在原来数据的位置private List<T9PinyinUnit> mT9PinyinUnitIndex;//用链表保存汉字拼音,多音字则长度大于1,单音字或字符串长度为1......}
例如:一串可能含汉字的字符串转换保存到若干PinyinUnit类型变量中.
//"Hi你说" {//Hi-HimPinyin=false;mT9PinyinUnitIndex.size=1;mStartPosition=0;{mT9PinyinUnitIndex.get(0).setPinyin("Hi");mT9PinyinUnitIndex.get(0).setNumber("44");}}{//你->ni3mPinyin=true;mT9PinyinUnitIndex.size=1;mStartPosition=2;{mT9PinyinUnitIndex.get(0).setPinyin()="ni";mT9PinyinUnitIndex.get(0).setNumber="64";}}{//说->shuo1,shui4,yue4mPinyin=true;mT9PinyinUnitIndex.size=3;mStartPosition=3;{{mT9PinyinUnitIndex.get(0).setPinyin()="shuo";mT9PinyinUnitIndex.get(0).setNumber="7486";};{mT9PinyinUnitIndex.get(1).setPinyin()="shui";mT9PinyinUnitIndex.get(1).setNumber="7484";};{mT9PinyinUnitIndex.get(2).setPinyin()="yue";mT9PinyinUnitIndex.get(2).setNumber="983";}}
从上述转换过程中可以看出,一串可能含汉字的字符串(如姓名)会解析保存到一个PinyinUnit类型链表中,每个PinyinUnit类型变量保存着一个汉字的拼音或者一串非汉字字符串,这就是我们想要的基本数据解析结果。
注意汉字转换为拼音可以用Java库pinyin4j. 这是相关链接:http://pinyin4j.sourceforge.net/
2.相关基本函数
(1)字符串(可能含汉字)解析函数
/** * @description 将一串字符串(可能含中文)解析保存到一个元素类型为PinyinUnit的链表中. * 调用此函数时,只需传入chineseString,并传入已初始化的元素类型为PinyinUnit的链表索引, * 其解析结果将会保存传入的元素类型为PinyinUnit的链表中. * @param chineseString需要转换的字符串 * @param pinyinUnit 元素类型为PinyinUnit的链表索引. */ public static void chineseStringToPinyinUnit(String chineseString,List<PinyinUnit> pinyinUnit);
详细解析格式如图1:
图1.T9数据解析格式
(2)T9输入字符串匹配函数
/** * @description 将T9输入字符串与保存解析后的结果(元素类型为PinyinUnit的链表)进行匹配 * @param pinyinUnits元素类型为PinyinUnit的链表的索引 * @param baseData 解析成元素类型为PinyinUnit的链表之前的原始数据 * @param searchT9搜索关键字('0'~'9','*','#') * @param chineseKeyWord保存与baseData匹配的关键字 * @return 如果匹配返回true,否则返回false. */ public static boolean matchPinyinUnits(final List<PinyinUnit> pinyinUnits, final String baseData, String search,StringBuffer chineseKeyWord);关键算法解析
1.T9匹配算法
匹配规则:汉字主要以声母,汉字全拼,及以声母位置开始的汉字全拼的子串来匹配;非汉字(可能是一串字符)就以其子串来匹配。
匹配情形:
(1).汉字A:(汉字A从声母位置开始的子串可匹配汉字A)
例如汉字:"汉"=>'han';则可匹配‘汉’的关键字有:"h","ha","han".
(2).非汉字B:(非汉字B的子串可匹配非汉字B)
例如非汉字:"how"; 则可匹配”how“的关键字有:"h","o","w","ho","ow","how".
(3).汉字C+汉字D: (汉字C声母或汉字C全拼)+汉字D从声母开始的子串可匹配
例如汉字"汉"+汉字"文":"hanwen";则可匹配"hanwen"的关键字有:"hw","hwe","hwen","hanw","hanwe","hanwen"
(4).汉字E+非汉字F: (汉字E的声母或汉字E的全拼)+非汉字F从第一字符开始的子串可匹配
例如汉字"汉"+非汉字"how":"hanhow";则可匹配"hanhow"的关键字有:"hh","hho","hhow","hanh","hanho","hanhow".
(5).非汉字G+汉字H: (非汉字G从任意位置到非汉字G最后一个字符的子串)+(汉字H从声母开始的子串)可匹配
例如非汉字"how"+汉字"汉":"howhan";则可匹配"howhan"的关键字有:"wh","wha","whan","owh","owha","owhan","howh","howha","howhan".
T9输入是{'0'~'9','*','#'}的组合,非汉字字符串可以转换为{'0'~'9','*','#'+其他字符};汉字则可先转换为拼音然后再转换为{'2'~'9'}的组合.T9英文字符与数字的对应关系如下:
1 2(ABC) 3(DEF) 4(GHI) 5(JKL) 6(MNO) 7(PQRS) 8(TUV) 9(WXYZ) * 0 #
匹配算法:字符串(可能含有汉字)解析为元素PinyinUnit的链表保存的数据后,就可以直接用关键字与其进行匹配.以字符串"说了么git???"为例,解析数据保存在元素为PinyinUnit的链表pinyinUnits中.如图2.
图2 T9数据解析简要格式
最初的想法是将这些结果进行排列组合,然后再来匹配。这里的组合结果有3*2*3*1种,但组合起来并不是我们想要的结果,因为我们不仅仅是匹配组合串中的子串,我们不能忽略汉字中声母可匹配的规则,所以这不是一种好办法。我们决定采取搜索关键字与PinyinUnit变量单个进行比较的规则来匹配.
算法思路如下:
从pinyinUnits的第一个PinyinUnit元素开始,将搜索关键字与此PinyinUnit的第一个T9PinyinUnit元素进行匹配;
(1):如果此PinyinUnit元素的T9PinyinUnit元素是搜索关键字起始位置开始的子串,说明搜索关键字部分匹配成功,则去掉已匹配的关键字,将余下的关键字作为搜索关键字,继续从pinyinUnits的下一个PinyinUnit元素的第一个T9PinyinUnit元素进行匹配,如果匹配成功,则进入步骤(1),如果匹配不成功则进入步骤(2);
(2):如果此PinyinUnit元素的T9PinyinUnit元素不是搜索关键字起始位置开始的子串,则说明不匹配,则从当前Pinyin元素的下一个T9PinyinUnit元素进行匹配,如果匹配成功,则进入步骤(1),如果匹配不成功则进入步骤(2);
截止条件:成功匹配搜索关键字返回true;搜索完所有情况,匹配不成功返回false;
(A)这种深度搜索的方法只匹配搜索了以某个 PinyinUnit开始的情况,如果匹配成功,则直接返回;
(B)若没有与搜索关键字匹配的结果,则需要将pinyinUnits中下一个PinyinUnit元素开始的链表按照上述方式匹配搜索一次,再根据其匹配搜索结果,判断进入步骤(A)还是(B).
(截止条件:成功匹配或pinyinUnits中以最后一个PinyinUnit元素为开始元素的链表也遍历完.)
相关代码链接
T9搜索联系人Demo:一个演示android T9搜索联系人的项目
代码链接:Github:https://github.com/handsomezhou/T9Search
CSDN:http://download.csdn.net/detail/zjqyjg/8171825
T9搜索库&T9搜索联系人Demo(支持多音字):将T9搜索数据解析和匹配接口制作成库,并演示android T9搜索联系人项目使用此库.
代码链接: Github:https://github.com/handsomezhou/T9SearchLibrary
CSDN:http://download.csdn.net/detail/zjqyjg/8171851
- android T9 搜索联系人分析与实现(支持多音字)
- android 拼音搜索联系人分析与实现(支持多音字,支持T9搜索,支持Qwerty搜索)
- android Qwerty 键盘搜索联系人分析与实现(支持多音字)
- T9搜索联系人的实现
- T9搜索联系人
- Android拨号盘,支持T9搜索和号码搜索
- Android Launcher T9搜索APP实现
- Android 联系人名字多音字的处理方法
- 通讯录T9搜索算法实现
- 玩爆你的手机联系人--T9搜索(一)
- 实现类似Android联系人搜索功能
- MTK的T9搜索流程分析
- 我的Android进阶之旅------>Android之AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字)
- 我的Android进阶之旅------>Android之AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字)
- android联系人搜索
- android 联系人搜索
- android 搜索通讯录联系人
- android中搜索联系人
- 【02-C语言】03-关键字、标识符、注释
- 周赛2(星期三之前补题完)
- 合并排序
- 源码管理 - perforce高级操作
- 抽象工厂模式概述
- android T9 搜索联系人分析与实现(支持多音字)
- 笔记
- 【02-C语言】04-常量、变量
- 10分钟掌握XML、JSON及其解析
- JAVA中int、String的类型转换
- 【02-C语言】05-进制
- 几款前端Js框架
- fluentd结合kibana、elasticsearch实时搜索分析hadoop集群日志
- 【android】android:clipChildren属性的运用——viewpager实现画廊(一屏多个Fragment)效果