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

主要思路

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

[WPF] 脱机环境实现支持拼音模糊搜索的AutoCompleteBox的更多相关文章

  1. ES6笔记(1) -- 环境配置支持

    系列文章 -- ES6笔记系列 虽然ES6已经发布一年多了,但在各大浏览器之中的支持度还不是很理想,在这查看ES6新特性支持度 Chrome的最新版本浏览器大部分已经支持,在Node.js环境上支持度 ...

  2. php检测iis环境是否支持htaccess

    php检测iis环境是否支持htaccess的方法. modrewrite.php <?php echo "mod_rewrite works"; ?> open_me ...

  3. Windows Presentation Foundation (WPF) 项目中不支持xxx的解决

    一般Windows Presentation Foundation (WPF) 项目中不支持xxx都是由于没引用相应的程序集导致,比如Windows Presentation Foundation ( ...

  4. 关于liunx 机器脱机环境(netcore)Nuget包迁移的问题

    首先nuget脱机环境是没办法加载第三方nuget包的,我这里的做法是使用nuget缓存文件(正确的做法还是推荐使用自己搭建的nuget服务器然后正常发布,这里只是做应急之需) 我们都知道项目的dot ...

  5. 【.NET6+WPF+Avalonia】开发支持跨平台的WPF应用程序以及基于ubuntu系统的演示

    前言:随着跨平台越来越流行,.net core支持跨平台至今也有好几年的光景了.但是目前基于.net的跨平台,大多数还是在使用B/S架构的跨平台上:至于C/S架构,大部分人可能会选择QT进行开发,或者 ...

  6. 解决c#,wpf程序带环境安装包体积太大问题

    在.net开发客户端的时候,一定会遇到用户没有安装.net环境的问题,特别是现在win7,win8,win10多系统并用的时间段,很多开发者使用的是4.5的目标环境,用户却是使用win7的系统,这样势 ...

  7. WPF ItemsControl 控件支持鼠标滚轮滑动

    此文章意在解决在WPF中ItemsControl类型的集合控件支持鼠标滚轮操作,并可控制滚动的速度. 第一步:给ItemsControl添加滚轮事件. this.listBox.AddHandler( ...

  8. 转:windows下使用gvim搭建简单的IDE编译环境(支持C/C++/Python等)

    原文来自于:http://www.cnblogs.com/zhuyp1015/archive/2012/06/16/2552269.html 使用gvim在windows环境下搭建简单的IDE环境可以 ...

  9. 扩展ArcGIS API for Silverlight/WPF 中的TextSymbol支持角度标注

    原文 http://blog.csdn.net/esricd/article/details/7587136 在ArcGIS API for Silverlight/WPF中原版的TextSymbol ...

  10. mac环境下支持PHP调试工具xdebug,不需要建项目server

    先让php支持xdebug 方式一: https://xdebug.org/download.php 下载相应的xdebug  可以到http://xdebug.org/wizard.php 把php ...

随机推荐

  1. Linux之命令提示符的颜色设置

    1.临时设置 执行下面的命令: export PS1="[\[\e[34;1m\]\u@\[\e[0m\]\[\e[32;1m\]\H\[\e[0m\] \[\e[31;1m\]\w\[\e ...

  2. Hangfire 使用笔记 任务可以分离到别的项目中,无需重复部署Hangfire,通过API方式通信。

    "巨人们"的地址 Hangfire Mysql: https://github.com/arnoldasgudas/Hangfire.MySqlStorage 在获取set表数据的 ...

  3. 关于ICMP隧道一点理解(起于修改wien-qq的记住密码)

    起 使用linux半年多以来,一直有一个我很需要但我无法完美解决的东西困扰这我-----(linux QQ) 目前我的解决方案是GitHub上的一个第三方QQ(有关ICMP隧道的搭建见 承,转) 但是 ...

  4. foxy rviz2 "rviz_common/Time"报错问题

    报错内容 The class required for this panel, 'rviz_common/Time', could not be loaded. Error: According to ...

  5. wordpress博客系统报错

    第一种,只显示nginx的默认网页 说明wordpress的网页配置文件没有被系统读取 我们就需要去查看nginx的配置文件/etc/nginx/conf.d/default.conf 首先,查看是不 ...

  6. Mysql 创建索引语句

    mysql有哪些索引 index 普通索引 alter table table_name add index index_name(column) 最基本的索引,没有任何限制 primary key ...

  7. C# 配置文件增加自定义节点

    话不多说直接开撸! 首先创建一个Config的文件夹然后新增一个后缀名为.config的文件 配置文件的代码如下: <?xml version="1.0" encoding= ...

  8. collections.sort()使用时注意的问题

    问题描述: 自定义排序一个List<Pair<Integer, Integer>>,根据pair的key由小到大排序,如果相同,则根据pair的value由大到小排序. 最开始 ...

  9. winform遍历控件的Controls.OfType<>方法

    页面TextBox控件较多时,可以使用类似的名字,方便遍历时整体的修改,可以使用Controls.OfType<TextBox>()获取所有文本框: 需要引用命名空间System.Linq ...

  10. JsonPath - 根据表达式路径解析Json

    JsonPath 在xml的使用过程中,对于xml的解析我们知道可以使用xpath的方式,随意的获取到我们想要的属性值.那么在使用json时,我们能不能实现同样的操作呢? 答案就是 json-path ...