Check string contain in list c#

Tweet0LinkedIn0Facebook0

There are many different scenarios where you might want to check a string against a list of substrings. Perhaps youre dealing with messy exception handling and have to compare the exception message against a list of known error messages to determine if the error is transient or not.

When you need to check a string for a list of substrings, the simplest approach is to use list.Any[] and string.Contains[], like this:

using System.Linq; public static bool ContainsAny[string s, List substrings] { if [string.IsNullOrEmpty[s] || substrings == null] return false; return substrings.Any[substring => s.Contains[substring, StringComparison.CurrentCultureIgnoreCase]]; }
Code language: C# [cs]

In this article, Ill show the non-Linq approach to this and then discuss the related problem of returning all matching substrings.

Table of Contents

  • Regular loop approach
  • Tests
  • Return all matching substrings
    • Using Linq
    • Non-Linq, generator method
    • Tests

Regular loop approach

Heres the non-Linq approach to this problem:

public static bool ContainsAny[string stringToTest, List substrings] { if [string.IsNullOrEmpty[stringToTest] || substrings == null] return false; foreach [var substring in substrings] { if [stringToTest.Contains[substring, StringComparison.CurrentCultureIgnoreCase]] return true; } return false; }
Code language: C# [cs]

Theres no real benefit to using this over the Linq approach. They both perform the same. Its a matter of preference.

Tests

Here are the tests that prove this code works. Notice it starts with the special cases. Its usually a good idea to start by testing special cases, that way you dont accidently forget to handle them.

[TestClass[]] public class StringUtilTests { #region Special cases [DataRow[null]] [DataRow[""]] [TestMethod[]] public void ContainsAny_WhenStringIsNullOrEmpty_ReturnsFalse[string stringToTest] { //arrange var substrings = new List[] { "a" }; //act var actual = StringUtil.ContainsAny[stringToTest, substrings]; //assert Assert.IsFalse[actual]; } [TestMethod[]] public void ContainsAny_WhenSubstringsListIsNull_ReturnsFalse[] { //arrange string stringToTest = "a"; List substrings = null; //act var actual = StringUtil.ContainsAny[stringToTest, substrings]; //assert Assert.IsFalse[actual]; } [TestMethod[]] public void ContainsAny_WhenSubstringsListIsEmpty_ReturnsFalse[] { //arrange string stringToTest = "a"; List substrings = new List[]; //act var actual = StringUtil.ContainsAny[stringToTest, substrings]; //assert Assert.IsFalse[actual]; } #endregion [TestMethod[]] public void ContainsAny_WhenContainsASubstring_ReturnsTrue[] { //arrange string stringToTest = "abc"; List substrings = new List[] { "a" }; //act var actual = StringUtil.ContainsAny[stringToTest, substrings]; //assert Assert.IsTrue[actual]; } [TestMethod[]] public void ContainsAny_WhenContainsASubstringWithDifferentCasing_ReturnsTrue[] { //arrange string stringToTest = "ABC"; List substrings = new List[] { "a" }; //act var actual = StringUtil.ContainsAny[stringToTest, substrings]; //assert Assert.IsTrue[actual]; } [TestMethod[]] public void ContainsAny_WhenDoesntContainASubtring_ReturnsFalse[] { //arrange string stringToTest = "abc"; List substrings = new List[] { "d" }; //act var actual = StringUtil.ContainsAny[stringToTest, substrings]; //assert Assert.IsFalse[actual]; } }
Code language: C# [cs]

Return all matching substrings

Instead of asking Does this string contain of these substring?, this related problem asks Which of the substrings does the string contain?. This may be useful if you need to display a list of the matching substrings. For example, lets say you are checking a textbox for any restricted words and you want to display all the restricted words to the user so they know which ones to erase.

Using Linq

You can use list.Where[] and string.Contains[] to get all the matching substrings, like this:

using System.Linq; public static IEnumerable WhereContains[string stringToTest, List substrings] { if [string.IsNullOrEmpty[stringToTest] || substrings == null] return Enumerable.Empty[]; return substrings.Where[substring => stringToTest.Contains[substring, StringComparison.CurrentCultureIgnoreCase]]; }
Code language: C# [cs]

Since this method is returning IEnumerable, if you want to return early, you have to return Enumerable.Empty[].

Non-Linq, generator method

Heres the non-Linq way to solve the problem. This is a generator method that uses yield return to stream matching substrings to the calling code as they are found:

public static IEnumerable WhereContains[string stringToTest, List substrings] { if [string.IsNullOrEmpty[stringToTest] || substrings == null] yield break; foreach [var substring in substrings] { if [stringToTest.Contains[substring, StringComparison.CurrentCultureIgnoreCase]] yield return substring; } }
Code language: C# [cs]

To return early from a generator method, you have to use yield break instead of a regular return, otherwise youll get the compiler error: Error CS1622 Cannot return a value from an iterator. Use the yield return statement to return a value, or yield break to end the iteration.

This performs the same as the Linq approach.

Note: You could return a List instead of returning an enumerable, but this has slightly worse performance.

Tests

Here are the non-special case unit tests for this WhereContains[] method:

[TestMethod[]] public void WhereContains_WhenContainsASubstring_ReturnsIt[] { //arrange string stringToTest = "abc"; var substrings = new List[] { "a" }; //act var actual = SubstringUtil.WhereContains[stringToTest, substrings]; //assert CollectionAssert.AreEqual[substrings, actual.ToList[]]; } [TestMethod[]] public void WhereContains_OnlyReturnsMatchingSubstrings[] { //arrange string stringToTest = "abc"; var substrings = new List[] { "a", "d" }; var expected = new List[] { "a" }; //act var actual = SubstringUtil.WhereContains[stringToTest, substrings]; //assert CollectionAssert.AreEqual[expected, actual.ToList[]]; } [TestMethod[]] public void WhereContains_WhenNoMatching_ReturnEmptyList[] { //arrange string stringToTest = "abc"; var substrings = new List[] { "d" }; var expected = new List[]; //act var actual = SubstringUtil.WhereContains[stringToTest, substrings]; //assert CollectionAssert.AreEqual[expected, actual.ToList[]]; }
Code language: C# [cs]
Tweet0LinkedIn0Facebook0

Video liên quan

Chủ Đề