Hi I have a collection of name type objects and I want to perform a wild card search on it. For example, if I provide a search Criteria *ABC
then the returned name should start with ABC
. If I provide a search Criteria ABC*
then returned name should end with 开发者_如何学PythonABC
. If I provide a search Criteria *ABC*
then returned name should contains ABC
. If I provide a search Criteria ?ABC
then returned name's second, third and fourth character should be ABC
respectively and first character can be any character.
Here's an extension method you might use
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("\\?", ".") + "$";
}
}
Use it as follows:
void Main()
{
var items = new[] { new MyObj { MyProperty = "ABC123" },
new MyObj { MyProperty = "123ABC" },
new MyObj { MyProperty = "123ABC456" },
};
var matches = items.MatchesWildcard(item => item.MyProperty, "???ABC");
}
public class MyObj
{
public string MyProperty {get;set;}
}
(WildcardToRegex taken from CodeProject)
I think you need Regex.Escape and Regex.IsMatch().
private IEnumerable<Item> FilterList(IEnumerable<Item> list, string query)
{
string pattern = QueryToRegex(query);
return list.Where(i => Regex.IsMatch(i.Name, pattern, RegexOptions.Singleline));
}
private static string QueryToRegex(string query)
{
return "^" + Regex.Escape(query).Replace("\\*", ".*").Replace("\\?", ".") + "$";
}
Note: Samuel Jack's answer was better in that his Regex was better, so shamefully fixed it here.
I think you need to use .Contains , .StartWith , .EndsWith
This article lists an extension method that also is compatible with Entity Framework and LINQ-to-entities.
Example usage:
var searchTerm = "*Inc";
var q = db.Customers
.WhereLike(c => c.CompanyName, searchTerm, '*')
.ToList();
Source code:
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 });
}
}
精彩评论