匹配中文字符串的拼音首字母或英文字符串的首字母缩写

时间:2023-01-28 07:56:47

原始需求:

有联系人名字为‘张三’、‘张三丰’,搜索‘ZS’可以通过系统提供的Contacts.CONTENT_FILTER_URI搜索到。但是匹配字符串高亮时,无法智能将‘张三’高亮。

细化需求

  1. 需要将中文转换为拼音
  2. 提取拼音的首字母以及所对应原字符串的index
  3. 获取匹配首字母所对应原字符串的index
  4. 根据index高亮字符串

资源库

由于需要将汉字转换为拼音,因此需要引入谷歌ContactsProvider源码里的core-libart.jar包和里面的一个源代码类:HanziToPinyin.java。想用最新的可以在谷歌源码里找到。

要是报错:Conversion to Dalvik format failed with error 1
在项目中新建一个文件夹mylib,把core-libart.jar从libs中移动到新建的mylib中,并右键add to build path

代码

添加一个数据类,用来存储匹配成功的字符下标。

public class HighlightIndex {
    public final int start;
    public final int end;
    public HighlightIndex(int start, int end) {
        this.start = start;
        this.end = end;
    }
}

核心代码

先获取中文全拼,再提取出首字母成一个姓名缩写字符串,在通过关键字匹配姓名缩写,最后将匹配成功的字符对应上原始字符串的下标。

/** * 获取首字母缩略字符匹配的下标 * @param input 原字符串 * @param prefix 高亮字符串 * @return 原字符串需要高亮的下标位置(start和end)List * @author zhuxh2 * */
    public static ArrayList<HighlightIndex> getAcronym(String input, String prefix) {

        ArrayList<Token> tokens = HanziToPinyin.getInstance().getTokens(input);
        //姓名缩写
        StringBuilder acronym = new StringBuilder();
        //缩写字母index
        ArrayList<HighlightIndex> indexs = new ArrayList<HighlightIndex>();
        //匹配后的缩写字母index
        ArrayList<HighlightIndex> indexsResult = new ArrayList<HighlightIndex>();

        int index = 0;
        if (tokens != null && tokens.size() > 0) {
            for (Token token : tokens) {
                if (Token.PINYIN == token.type) {
                    acronym.append(token.target.charAt(0));
                    indexs.add(new HighlightIndex(index, index+1));
                    index++;
                } else {
                    acronym.append(token.source.charAt(0));
                    indexs.add(new HighlightIndex(index, index+1));
                    index = index + token.source.length();
                    while(index < input.length() && input.charAt(index) == ' ')
                        index++;
                }
            }
            int start = indexOfWordPrefix(acronym, prefix);
            if(start != -1)
                for(int j = start; j < start + prefix.length(); j++) {
                    indexsResult.add(indexs.get(j));
                }

        }
        return indexsResult;
    }

说一大堆没有直接来个源码干脆清晰
没有源码的技术博客不是好猿猴
附上源码