glosrob
glosrob

Reputation: 6715

Find any entities that contain any one string from a list

I can't quite get my head around this one for some reason.

Say we have a class Foo

public class Foo
{
    public string Name {get;set;}
}

And we have a generic list of them. I want to search through the generic list and pick out those that have a Name that contains any from a list of strings.

So something like

var source = GetListOfFoos();//assume a collection of Foo objects
var keywords = GetListOfKeyWords();//assume list/array of strings
var temp = new List<Foo>();
foreach(var keyword in keywords)
{
    temp.AddRange(source.Where(x => x.Name.Contains(keyword));
}

This issue here being a) the loop (doesn't feel optimal to me) and b) each object might appear more than once (if the name was 'Rob StackOverflow' and there was a keyword 'Rob' and keyword 'Stackoverflow').

I guess I could call Distinct() but again, it just doesn't feel optimal.

I think I'm approaching this incorrectly - what am I doing wrong?


Upvotes: 0

Views: 391

Answers (2)

Chris Doggett
Chris Doggett

Reputation: 20747

Put the keywords into a HashSet for fast lookup, so that you're not doing a N2 loop.

HashSet<string> keywords = new HashSet<string>(GetListOfKeyWords(), StringComparer.InvariantCultureIgnoreCase);

var query = source.Where(x => keywords.Contains(x.Name));

EDIT: Actually, I re-read the question, and was wrong. This will only match the entire keyword, not see if the Name contains the keyword. Working on a better fix.

I like MarcinJuraszek's answer, but I would also assume you want case-insensitive matching of the keywords, so I'd try something like this:

var query = source.Where(f => keywords.Any(k => f.Name.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0));

Upvotes: 1

MarcinJuraszek
MarcinJuraszek

Reputation: 125610

I want to search through the generic list and pick out those that have a Name that contains any from a list of strings.

Sounds rather easy:

var query = source.Where(e => keywords.Any(k => e.Name.Contains(k)));

Add ToList() to get results as a List<Foo>:

var temp = query.ToList();

Upvotes: 2

Related Questions