Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ search using WildCards character like *, %,?

Tags:

c#

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 ABC. 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.

like image 627
Sunil Avatar asked Jun 23 '10 13:06

Sunil


People also ask

What is any () in LinQ?

The Any operator is used to check whether any element in the sequence or collection satisfy the given condition. If one or more element satisfies the given condition, then it will return true. If any element does not satisfy the given condition, then it will return false.


2 Answers

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)

like image 135
Samuel Jack Avatar answered Oct 04 '22 20:10

Samuel Jack


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.

like image 45
ErikHeemskerk Avatar answered Oct 04 '22 20:10

ErikHeemskerk