Simple string keyword search using ExtensionMethods and LINQ

This is a case I ran into recently. I need to create a multiple OR condition with LINQ. I have a list of user names and I wish to create a simple search where I can match any first name/middle name/last name combination with any of the names in my list. The search “Brian Pedersen” should match any combination such as “Brian Jensen”, “Brian Steen Pedersen”, “Johan Pedersen” and “Brian Pedersen”.

This can be achieved very simply using LINQ. I need to split my search term into single words and use the Any LINQ statement:

// Remember to include LINQ
using System.Linq;

// This is the string to search within
string userName = "Brian Steen Pedersen";
// This is the search string
string searchString = "Brian Pedersen";
// I split the search string into indiviual words
string[] searchTerms = seachString.Split(' ');
// ... and return TRUE if any of the words is found inside the userName string
bool found = searchTerms.Any(searchTerm => userName.ToLower().Contains(searchTerm.ToLower()));

All I have to do is to put the code into a function and I can call this function whenever I need it:

public bool ContainsAny(string userName, IEnumerable<string> searchTerms)
{
  return searchTerms.Any(searchTerm => userName.ToLower().Contains(searchTerm.ToLower()));
}

Now, wouldn’t it be nice if the “ContainsAny” was a function of the String object? The String object Contains function only returns true for any exact match, and that’s not what I want. I want my ContainsAny function.

The String object can be extended using an Extension Method. Extension methods enable you to add methods to existing types without creating or modifying the original type. Read more about extension methods here.

This is 2 extension methods, extending the String object with ContainsAny and ContainsAll:

public static class StringExtension
{
  public static bool ContainsAny(this string str, IEnumerable<string> searchTerms)
  {
    return searchTerms.Any(searchTerm => str.ToLower().Contains(searchTerm.ToLower()));
  }  

  public static bool ContainsAll(this string str, IEnumerable<string> searchTerms)
  {
    return searchTerms.All(searchTerm => str.ToLower().Contains(searchTerm.ToLower()));
  }
}

With this code I can now use ContainsAny directly on the String object:

string userName = "Brian Steen Pedersen";
string searchString = "Brian Pedersen";

bool found = userName.ContainsAny(searchString.Split(' '));

I can even combine it with other LINQ statements. Lets assume that my users is stored in a generic List<string>. I can now find all users with this line of code:

// This is my fictive list of all users
List<string> allUsers = UserRepository.GetAllusers();
// This is my search string
string searchString = "Brian Pedersen";
// Here is all my users that match any words in the search string
List<string> foundUsers = allUsers.FindAll(s => s.ContainsAny(searchString.Split(' ')));
About these ads

About Brian Pedersen

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, c#, General .NET and tagged , , . Bookmark the permalink.

One Response to Simple string keyword search using ExtensionMethods and LINQ

  1. Shimmy says:

    And how would I convert this extension method to be supported by Linq to Entities?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s