8

I am trying to find if a list of strings contains a specific string in C#. for example: Suppose I have 3 entries in my list

list<string> s1 = new List<string>(){
  "the lazy boy went to the market in a car", 
  "tom", 
  "balloon"};
string s2 = "market";

Now I want to return true if s1 contains s2, which it does in this case.

return s1.Contains(s2);

This returns false which is not what I want. I was reading about Predicate but could not make much sense out of it for this case. Thanks in advance.

3 Answers 3

25

The simplest way is to search each string individually:

bool exists = s1.Any(s => s.Contains(s2));

The List<string>.Contains() method is going to check if any whole string matches the string you ask for. You need to check each individual list element to accomplish what you want.

Note that this may be a time-consuming operation, if your list has a large number of elements in it, very long strings, and especially in the case where the string you're searching for either does not exist or is found only near the end of the list.

Sign up to request clarification or add additional context in comments.

4 Comments

One note on it being a time consuming operation, .Any( will stop processing after the first true is returned so in the OP's example it only called Contains on the first string. Also for large lists this is a good case to use AsParallel() to split up the search across multiple threads bool exists = s1.AsParallel().Any(s => s.Contains(s2));
@ScottChamberlain: exactly. That's why I qualified my comment by "large number of elements" or "long strings", and wrote "especially in the case where the string you're searching for...is found only near the end of the list". The performance is dependent on how much data there is to deal with, and how early the expensive iteration can terminate. In the example given, it doesn't matter at all; even if the string wasn't found at all, there's not enough data to notice the cost. A real world example could be quite different. And yes, concurrency can help, if you've got the CPU cores to spare.
And to explain the Predicate<> question, while Any<> is a Linq method, where the lambda arrow is typed as a Func<string, bool> in this case, the List<> class also has an older Exists instance method where the same arrow gets the type Predicate<string>. Before the Func<,> delegate type was introduced, less general delegate types were used depending on context.
how about: s1.Where(s => s.IndexOf(s2, StringComparision.Ordinal) != -1) This returns you the list of items that matches with s2
2

Contains' alternative could be IndexOf:

var res = s1.Any(s => s.IndexOf(s2, StringComparison.Ordinal) >= 0)

StringComparison.Ordinal passed as parameter because Contains() also use it internally.

Comments

1

Peter Duniho's answer is generally the best way. I am providing an alternate solution. This one does not require LINQ, lamdas, or loops. This only requires string built-in type's methods.

string.Concat(listOfString).Contains("data");

Note: This approach can lead to incorrect results. For example:

string.Concat("da", "ta").Contains("data");

will return true when it should be false;

1 Comment

If you do this with Join instead and specify a delimiter you could reduce the risk of those incorrect results you mention

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.