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. shell脚本的调试

    参数: -n :读一遍脚本中的命令但不执行,用于检查脚本中的语法错误 -v :一边执行脚本,一边将执行过的脚本命令打印到标准错误输出 -x :提供跟踪执行信息,将执行的每一条命令和结果依次打印出来 使 ...

  2. Qt-FFmpeg开发-视频播放(5)

    音视频/FFmpeg #Qt Qt-FFmpeg开发-视频播放[软/硬解码 + OpenGL显示YUV/NV12] 目录 音视频/FFmpeg #Qt Qt-FFmpeg开发-视频播放[软/硬解码 + ...

  3. AutoLayout与UIbutton

    1.UIButton贴近右边,高度固定,宽度跟随标题变化 class TestButton: UIButton { } class ViewController: UIViewController { ...

  4. ros2 foxy订阅话题问题

    代码片段 这部分代码在galactic版本编译是OK的,可在foxy下编译就出了问题 TeleopPanel::TeleopPanel(QWidget* parent) : rviz_common:: ...

  5. 8.24考试总结(NOIP模拟47)[Prime·Sequence·Omeed]

    时间带着明显的恶意,缓缓在我的头顶流逝. T1 Prime 解题思路 成功没有签上到... 一看数据范围 \(R-L+1\le 10^7,R\le 10^{14}\) ,这肯定是判断范围内的数字是否可 ...

  6. css摩天轮

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8 ...

  7. m3u8文件转换mp4 ffmpeg

    m3u8文件转换mp4 ffmpeg 命令行执行下面语句: ffmpeg -i input.m3u8 -c copy output.mp4 ffmpeg.exe 和 input.m3u8 放在同一目录 ...

  8. 妙用OSGraph:发掘GitHub知识图谱上的开源故事

    1. 何为OSGraph? OSGraph (Open Source Graph) 是一个开源图谱关系洞察工具,基于GitHub开源数据全域图谱,实现开发者行为.项目社区生态的分析洞察.可以为开发者. ...

  9. java多线程编程:你真的了解线程中断吗?

    java.lang.Thread类有一个 interrupt 方法,该方法直接对线程调用.当被interrupt的线程正在sleep或wait时,会抛出 InterruptedException 异常 ...

  10. spring jpa restful请求示例

    创建项目 导入jar包mysql 数据库和连接池jar <dependency> <groupId>org.springframework.boot</groupId&g ...