如何用LINQ实现带通配符的WinForms客户列表过滤?
实现通配符过滤的LINQ方案
要支持?(匹配单个任意字符)和*(匹配任意多个任意字符)的通配符过滤,我们可以借助正则表达式把通配符转换成可匹配的规则,再结合LINQ完成过滤。下面是完整的实现步骤:
1. 写一个通配符转正则的辅助方法
首先需要把用户输入的通配符模式转换成正则表达式语法,这个方法会帮我们处理正则特殊字符的转义,以及通配符的替换:
using System.Text.RegularExpressions; // 辅助方法:将通配符模式转换为正则表达式 private string WildcardToRegex(string pattern) { // 先转义所有正则元字符(比如.、$、+这些),再替换通配符 // ^和$确保完全匹配整个字符串(如果需要包含匹配可以去掉这两个符号) return "^" + Regex.Escape(pattern).Replace("\\?", ".").Replace("\\*", ".*") + "$"; }
Regex.Escape(pattern):避免用户输入的内容里包含正则特殊字符(比如.)导致匹配出错;Replace("\\?", "."):把通配符?转换成正则的.(匹配单个任意字符);Replace("\\*", ".*"):把通配符*转换成正则的.*(匹配0个或多个任意字符);- 前后的
^和$:确保是完全匹配整个姓名/姓氏(比如输入g??fy只会匹配刚好5个字符、开头g结尾fy的字符串),如果需要改成包含匹配(比如输入*fy匹配任何包含fy的字符串),直接去掉^和$即可。
2. 修改LINQ过滤逻辑
接下来替换你原来的过滤代码,用正则匹配来实现通配符过滤,同时保留大小写不敏感的特性:
// 获取用户输入的通配符,先去除首尾空格 string nameFilter = txtName.Text.Trim(); string surnameFilter = txtSurname.Text.Trim(); // 处理空输入:如果用户没输入内容,就匹配所有项 Regex nameRegex = string.IsNullOrEmpty(nameFilter) ? new Regex(".*", RegexOptions.IgnoreCase) : new Regex(WildcardToRegex(nameFilter), RegexOptions.IgnoreCase); Regex surnameRegex = string.IsNullOrEmpty(surnameFilter) ? new Regex(".*", RegexOptions.IgnoreCase) : new Regex(WildcardToRegex(surnameFilter), RegexOptions.IgnoreCase); // 执行过滤:同时满足姓名和姓氏的通配符匹配 List<Customer> customersFiltered = Customers .Where(customer => nameRegex.IsMatch(customer.Name) && surnameRegex.IsMatch(customer.Surname)) .ToList(); // 后续处理customersFiltered...
这段代码的逻辑:
- 当用户的姓名/姓氏输入为空时,用
.*匹配所有内容,不会过滤掉任何项; RegexOptions.IgnoreCase实现了和原来ToLower()一样的大小写不敏感匹配;Where方法同时验证姓名和姓氏的匹配条件,替代了你原来两次FindAll的写法,更简洁高效。
测试示例
- 输入姓名为
g??fy:会匹配Goofy、Gaffy这类刚好5个字符、开头g结尾fy的姓名; - 输入姓氏为
g*y:会匹配Gooofy、Gaaaaaaay这类以g开头、y结尾(中间任意长度字符)的姓氏; - 如果去掉
WildcardToRegex里的^和$,输入*fy还会匹配AbcFyXyz这类包含fy的字符串。
内容的提问来源于stack exchange,提问作者pinguinone
相关产品推荐
相关产品推荐

