首页 > 其他分享 >拼音模糊搜索的AutoCompleteBox

拼音模糊搜索的AutoCompleteBox

时间:2024-07-28 22:08:12浏览次数:8  
标签:匹配 拼音 汉字 AutoCompleteBox 搜索 字符串 phoneticizes string

[WPF] 脱机环境实现支持拼音模糊搜索的AutoCompleteBox

 

AutoCompleteBox是一个常见的提高输入效率的组件,很多WPF的第三方控件库都提供了这个组件,但基本都是字符串的子串匹配,不支持拼音模糊匹配,例如无法通过输入ldhliudehua匹配到刘德华。要实现拼音模糊搜索功能,通常会采用分词、数据库等技术对待匹配数据集进行预处理。某些场景受制于条件限制,无法对数据进行预处理,本文将介绍在这种情况下如何实现支持拼音模糊搜索的AutoCompleteBox,先来看下实现效果。
image

主要思路

WPF中并没有AutoCompleteBox控件,我们可以使用TextBox输入搜索内容,用Popup+ListBox显示匹配到的提示内容。拼音模糊匹配汉字则采用字符串匹配的方式来解决,也就是搜索字符串和待匹配数据集的内容全部转换为拼音字符串,然后进行子串匹配。这里有三个问题需要解决。

  1. 汉字转换为拼音。
  2. 拼音如何匹配。 例如ldhlidhldhualiudehuadhuahua等都能匹配到刘德华
  3. 匹配后的内容高亮显示。 当输入dhua匹配到刘德华时需要把德华两个字高亮。

汉字转换拼音

微软为了开发者实现国际化语言的互转,提供了Microsoft Visual Studio International Pack,这个扩展包里面有中文、日文、韩文、英语等各国语言包,并提供方法实现互转、获取拼音、获取字数、甚至获取笔画数等等。下载Microsoft Visual Studio International Pack 1.0 SR1安装后,在安装目录中找到ChnCharInfo.dll,然后在项目中添加引用。
ChnCharInfo.dll获取汉字的拼音时只能传入单个字符,因此只能把汉字字符串拆分成一个个字符处理,由于汉字存在多音字情况以及缺少语义信息,获取的拼音组合可能是多个,例如输入长江,返回的是changjiangzhangjiang。汉字转拼音的方法如下:

/// <summary>
/// 获取汉字拼音
/// </summary>
/// <param name="str">待处理包含汉字的字符串</param>
/// <param name="split">拼音分隔符</param>
/// <returns></returns>
public static List<string> GetChinesePhoneticize(string str, string split = "")
{
    List<string> result = new List<string>();
    char[] chs = str.ToCharArray();
    Dictionary<int, List<string>> totalPhoneticizes = new Dictionary<int, List<string>>();
    for (int i = 0; i < chs.Length; i++)
    {
        var phoneticizes = new List<string>();
        if (ChineseChar.IsValidChar(chs[i]))
        {
            ChineseChar cc = new ChineseChar(chs[i]);
            phoneticizes.AddRange(cc.Pinyins.Where(r => !string.IsNullOrWhiteSpace(r)).ToList<string>().ConvertAll(p => Regex.Replace(p, @"\d", "").ToLower()).Distinct());
        }
        else
        {
            phoneticizes.Add(chs[i].ToString());
        }
        if (phoneticizes.Any())
            totalPhoneticizes[i] = phoneticizes;
    }

    foreach (var phoneticizes in totalPhoneticizes)
    {
        var items = phoneticizes.Value;
        if (result.Count <= 0)
        {
            result = items;
        }
        else
        {
            var newtotalPhoneticizes = new List<string>();
            foreach (var totalPingYin in result)
            {
                newtotalPhoneticizes.AddRange(items.Select(item => totalPingYin + split + item));
            }
            newtotalPhoneticizes = newtotalPhoneticizes.Distinct().ToList();
            result = newtotalPhoneticizes;
        }
    }
    return result;
}

拼音匹配算法

汉字转换后的拼音字符串有多组,只要搜索字符串转换的拼音组合有一组与待匹配字符串转换的拼音组合中匹配,则认为匹配成功,为了后续高亮显示,需要记录下匹配的起始位置以及匹配的子串长度。代码如下:

public static bool fuzzyMatchChar(string character, string input, out int matchStart, out int matchCount)
{
    List<string> regexs = GetChinesePhoneticize(input);
    List<string> targetStr = GetChinesePhoneticize(character, " ");
    matchStart = -1;
    matchCount = 0;
    foreach (string regex in regexs)
    {
        foreach (string target in targetStr)
        {
            if (PhoneticizeMatch(regex, target.Split(' '), out matchStart, out matchCount))
                return true;
        }
    }
    return false;
}

这里的PhoneticizeMatch方法是拼音匹配算法的核心,是在【算法】拼音匹配算法这篇博文中算法的基础上稍作修改,详细的思路及图解可阅读这篇博文。

高亮匹配的子串

WPF中可以通过TextEffectPositionStartPositionCount以及Foreground属性设置字符串中需要高亮内容的起始位置、长度以及高亮颜色。前面拼音匹配算法中获取了匹配成功子串的起始位置和长度,也正是为此做准备。之前在WPF使用TextBlock实现查找结果高亮显示一文中有详细介绍思路和代码,此处不再赘述。

小结

本文介绍了在不依赖数据库及分词的情况下如何实现拼音模糊搜索并在目标字符串中高亮显示,方法中也存在诸多不足需要完善的地方。

  1. 匹配策略存在误匹配。例如输入,可以匹配出拼音为shi的所有汉字。
  2. 匹配算法效率不够高。测试过程中,待匹配数据集中模拟了500条数据,匹配耗时大概在400~500ms左右。

代码示例

ChinesePhoneticizeFuzzyMatch

标签:匹配,拼音,汉字,AutoCompleteBox,搜索,字符串,phoneticizes,string
From: https://www.cnblogs.com/Leo_wl/p/18328939

相关文章

  • LeetCode530. 二叉搜索树的最小绝对差
    题目链接:https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/题目叙述:给你一个二叉搜索树的根节点root,返回树中任意两不同节点值之间的最小差值。差值是一个正数,其数值等于两值之差的绝对值。示例1:输入:root=[4,2,6,1,3]输出:1示例2:输......
  • LeetCode700. 二叉搜索树中的搜索
    题目链接:https://leetcode.cn/problems/search-in-a-binary-search-tree/description/题目叙述:给定二叉搜索树(BST)的根节点root和一个整数值val。你需要在BST中找到节点值等于val的节点。返回以该节点为根的子树。如果节点不存在,则返回null。示例1:输入:root=[1......
  • 如何在实际应用中利用B树进行搜索
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;推荐专栏《10天学会使用asp.net编程AI大模型》,目前已完成所有内容。一顿烧烤不到的费用,让人能紧跟时代的浪潮。从普通网站,到公众号、小程序,再到AI大模型网站。干货满满。学成后可......
  • 【无线充电车辆路线和速度预测】使用随机搜索优化方法同时具有路由和速度分配的模型研
    ......
  • 【无线充电车辆路线和速度预测】使用随机搜索优化方法同时具有路由和速度分配的模型研
    ......
  • 二分搜索
    二分搜索2024年7月25日21:27   正常二分思想重点是遇到不同的数怎么定边界,怎么记录答案。特殊情况:没有数字或者只有一个数,直接判断返回先定一个ans=-1用于记录答案,l、r记录左右边界看中点数值,比target小,说明比target的的数字在右边,l=mid+1比target大,ans=mid,还需......
  • 利用Elasticsearch实现地理位置、城市搜索服务
    最近用到一些简单的地理位置查询接口,基于当前定位获取用户所在位置信息(省市区),然后基于该信息查询当前区域的......提供服务。然后就自己研究了下GIS,作为一个程序员。自己能不能实现这个功能呢?答案当然是可以。立即开干。思路:找到数据,写入数据库,利用Elasticsearch强大的搜索能力......
  • 手把手教你集成GraphRag.Net:打造智能图谱搜索系统
        在人工智能和大数据发展的背景下,我们常常需要在项目中实现知识图谱的应用,以便快速、准确地检索和使用信息。        今天,我将向大家详细介绍如何在一个新的.NET项目中集成GraphRag.Net,这是一个参考GraphRag实现的.NET版本,能够实现图谱数据的存储、检索、和问......
  • Java实现一颗二叉搜索树的增删查改操作
    Java实现一颗二叉搜索树的增删查改操作:树节点:packagetest.tree;publicclassTreeNode{privateintval;privateTreeNodeleft;privateTreeNoderight;publicTreeNode(intval){this.val=val;this.left=null;th......
  • 稠密向量+稀疏向量+全文搜索+张量重排=最佳检索RAG?
    RAG中的混合检索如下图:为什么要混合搜索(multi-wayrecall)?越来越多的人认为,仅仅依靠向量搜索,通常是密集向量,可能并不总是产生令人满意的结果。当用户的特定查询关键字与存储的数据不精确匹配时,这种限制就会变得明显。这是因为向量本身不能表示精确的语义信息:向量可以表示一......