I have a Filter Method in my User Class, that takes in a list of Users and a string of search terms. Currently, the FindAll predicate splits the terms on spaces then returns a match if any of the searchable properties contain any part of the terms.
public static List<User> FilterBySearchTerms( List<User> usersToFilter, string searchTerms, bool searchEmailText )
{
return usersToFilter.FindAll( user =>
{
// Convert to lower case for better comparison, trim white space and then split on spaces to search for all terms
string[] terms = searchTerms.ToLower().Trim().Split( ' ' );
foreach ( string term in terms )
{
// TODO: Is this any quicker than two separate ifs?
if (
(searchEmailText && user.Email.ToLower().Contains( term ))
|| (
user.FirstName.ToLower().Contains( term ) || user.Surname.ToLower().Contains( term )
|| user.Position.ToLower().Contains( term ) || user.Company.ToLower().Contains( term )
|| user.Office.ToLower().Contains( term )
|| user.Title.ToLower().Contains( term )
)
)
return true;
// Search UserID by encoded UserInviteID
else
{
int encodedID;
if ( int.TryParse( term, out encodedID ) )
{
User fromInvite = GetByEncodedUserInviteID( encodedID );
if ( fromInvite != null && fromInvite.ID.HasValue && fromInvite.ID.Value == user.ID )
return true;
}
}
}
return false;
} );
}
I have received a new requirement so that the ordering is now important. For example, a search for 'Mr Smith' should have Mr Adam Smith ahead of Mrs Eve Smith, which might make my use of Contains inappropriate. However, the most important thing is the number of property/part of term matches.
I'm thinking I could have a couple of counters to keep track of complete term matches and partial matches, then order by those two. I'm also open to suggestions on how the Filter method can be improved - perhaps using something else entirely.