C# 使用通配符(如*,%,?)进行LINQ搜索,?
您好,我有一个名称类型对象的集合,我想对其执行通配符搜索。例如,如果我提供搜索条件C# 使用通配符(如*,%,?)进行LINQ搜索,?,c#,C#,您好,我有一个名称类型对象的集合,我想对其执行通配符搜索。例如,如果我提供搜索条件*ABC,则返回的名称应以ABC开头。如果我提供了搜索条件ABC*,那么返回的名称应以ABC结尾。如果我提供了搜索条件*ABC*,那么返回的名称应该包含ABC。如果我提供一个搜索条件,那么返回名称的第二、第三和第四个字符应该分别是ABC,第一个字符可以是任何字符。我认为您需要使用.Contains、.StartWith、.EndsWith我认为您需要Regex.Escape和Regex.IsMatch() priv
*ABC
,则返回的名称应以ABC
开头。如果我提供了搜索条件ABC*
,那么返回的名称应以ABC
结尾。如果我提供了搜索条件*ABC*
,那么返回的名称应该包含ABC
。如果我提供一个搜索条件,那么返回名称的第二、第三和第四个字符应该分别是ABC
,第一个字符可以是任何字符。我认为您需要使用.Contains、.StartWith、.EndsWith我认为您需要Regex.Escape和Regex.IsMatch()
private IEnumerable过滤器列表(IEnumerable列表,字符串查询)
{
字符串模式=QueryToRegex(查询);
其中(i=>Regex.IsMatch(i.Name,pattern,RegexOptions.Singleline));
}
私有静态字符串QueryToRegex(字符串查询)
{
返回“^”+Regex.Escape(查询)。替换(“\\*”,“*”)。替换(“\\?”,“)+“$”;
}
注意:更好的是他的正则表达式更好,所以可耻地在这里修复了它。这里有一个扩展方法,您可以使用
public static class EnumerableExtensions
{
public static IEnumerable<T> MatchesWildcard<T>(this IEnumerable<T> sequence, Func<T,string> expression, string pattern)
{
var regEx = WildcardToRegex(pattern);
return sequence.Where(item => Regex.IsMatch(expression(item), regEx));
}
public static string WildcardToRegex(string pattern)
{
return "^" + Regex.Escape(pattern).
Replace("\\*", ".*").
Replace("\\?", ".") + "$";
}
}
(WildcardToRegex摘自)这列出了一个扩展方法,它也与实体框架和LINQ to实体兼容
用法示例:
var searchTerm = "*Inc";
var q = db.Customers
.WhereLike(c => c.CompanyName, searchTerm, '*')
.ToList();
源代码:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
public static class LinqExtensions
{
public static IQueryable<TSource> WhereLike<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, string>> valueSelector,
string value,
char wildcard)
{
return source.Where(BuildLikeExpression(valueSelector, value, wildcard));
}
public static Expression<Func<TElement, bool>> BuildLikeExpression<TElement>(
Expression<Func<TElement, string>> valueSelector,
string value,
char wildcard)
{
if (valueSelector == null)
throw new ArgumentNullException("valueSelector");
var method = GetLikeMethod(value, wildcard);
value = value.Trim(wildcard);
var body = Expression.Call(valueSelector.Body, method, Expression.Constant(value));
var parameter = valueSelector.Parameters.Single();
return Expression.Lambda<Func<TElement, bool>>(body, parameter);
}
private static MethodInfo GetLikeMethod(string value, char wildcard)
{
var methodName = "Contains";
var textLength = value.Length;
value = value.TrimEnd(wildcard);
if (textLength > value.Length)
{
methodName = "StartsWith";
textLength = value.Length;
}
value = value.TrimStart(wildcard);
if (textLength > value.Length)
{
methodName = (methodName == "StartsWith") ? "Contains" : "EndsWith";
textLength = value.Length;
}
var stringType = typeof(string);
return stringType.GetMethod(methodName, new Type[] { stringType });
}
}
使用系统;
使用System.Collections.Generic;
使用系统数据;
使用System.Data.Object;
使用System.Data.Objects.DataClass;
使用System.Linq;
使用System.Linq.Expressions;
运用系统反思;
公共静态类LinqExtensions
{
公共静态可在何处查询(
这是可靠的消息来源,
表达式值选择器,
字符串值,
字符(通配符)
{
返回source.Where(BuildLikeExpression(valueSelector,value,通配符));
}
公共静态表达式BuildLikeExpression(
表达式值选择器,
字符串值,
字符(通配符)
{
如果(valueSelector==null)
抛出新ArgumentNullException(“valueSelector”);
var方法=GetLikeMethod(值,通配符);
value=value.Trim(通配符);
var body=Expression.Call(valueSelector.body,方法,Expression.Constant(value));
var parameter=valueSelector.Parameters.Single();
返回表达式.Lambda(主体,参数);
}
私有静态MethodInfo GetLikeMethod(字符串值,字符通配符)
{
var methodName=“Contains”;
var textLength=value.Length;
value=value.TrimEnd(通配符);
如果(textLength>value.Length)
{
methodName=“StartsWith”;
textLength=value.Length;
}
value=value.TrimStart(通配符);
如果(textLength>value.Length)
{
methodName=(methodName=“StartWith”)?“包含”:“EndsWith”;
textLength=value.Length;
}
var stringType=typeof(字符串);
返回stringType.GetMethod(methodName,新类型[]{stringType});
}
}
我们在这里谈论的是LINQ对对象,还是LINQ对SQL?@Samuel:看起来像是LINQ对对象,因为他提到他有一个“对象集合”.你的正则表达式方法(你复制的,我从头顶键入的)比我的好。@ErikHeemskerk-当你有谷歌的时候,为什么还要麻烦学习正则表达式语法呢?:-)啊,但无论如何这都是徒劳的,因为塞缪尔·杰克发布了一个更好的方法来将通配符表达式翻译成正则表达式;我的工作不正常。
var searchTerm = "*Inc";
var q = db.Customers
.WhereLike(c => c.CompanyName, searchTerm, '*')
.ToList();
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
public static class LinqExtensions
{
public static IQueryable<TSource> WhereLike<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, string>> valueSelector,
string value,
char wildcard)
{
return source.Where(BuildLikeExpression(valueSelector, value, wildcard));
}
public static Expression<Func<TElement, bool>> BuildLikeExpression<TElement>(
Expression<Func<TElement, string>> valueSelector,
string value,
char wildcard)
{
if (valueSelector == null)
throw new ArgumentNullException("valueSelector");
var method = GetLikeMethod(value, wildcard);
value = value.Trim(wildcard);
var body = Expression.Call(valueSelector.Body, method, Expression.Constant(value));
var parameter = valueSelector.Parameters.Single();
return Expression.Lambda<Func<TElement, bool>>(body, parameter);
}
private static MethodInfo GetLikeMethod(string value, char wildcard)
{
var methodName = "Contains";
var textLength = value.Length;
value = value.TrimEnd(wildcard);
if (textLength > value.Length)
{
methodName = "StartsWith";
textLength = value.Length;
}
value = value.TrimStart(wildcard);
if (textLength > value.Length)
{
methodName = (methodName == "StartsWith") ? "Contains" : "EndsWith";
textLength = value.Length;
}
var stringType = typeof(string);
return stringType.GetMethod(methodName, new Type[] { stringType });
}
}