简体   繁体   中英

How to retrieve the value passed in string.Contains method?

Is it possible to retrieve the value passed in the string.Contains method?

The usage scenario would be something like this:

foreach (string x in myList)
{
    if (x.Contains("Salt") || x.Contains("Sugar") || x.Contains("Pepper"))
    {
        MessageBox.Show("The ingredient found in this line of myList is: " + //the ingredient found)
    }
}

The objective is to AVOID having to repeat code. Right now I have to do the following to achieve the desired result:

foreach (string x in myList)
{
    if (x.Contains("Salt"))
    {
        MessageBox.Show("The ingredient found in this line of myList is: Salt");
    }

    if (x.Contains("Sugar"))
    {
        MessageBox.Show("The ingredient found in this line of myList is: Sugar");
    }

    if (x.Contains("Pepper"))
    {
        MessageBox.Show("The ingredient found in this line of myList is: Pepper");
    }
}

If it's not possible is there any alternative?

Thanks in advance!

You could use the FirstOrDefault LINQ extension method and write something like this:

string[] ingredients = { "Salt", "Sugar", "Pepper" };
foreach (string x in myList)
{
    string ingredient = ingredients.FirstOrDefault(x.Contains); // i.e., i => x.Contains(i)
    if (ingredient != null)
    {
        MessageBox.Show("The ingredient found in this line of myList is: " + ingredient);
    }
}

If that's a little too cryptic for you, then create an extension method with a descriptive name:

// Put this in a static class somewhere.
public static string FindAny(this string s, params string[] values)
{
    return values.FirstOrDefault(s.Contains);
}

And call it like this:

string ingredient = x.FindAny(ingredients);
// Or, at the expense of extra memory allocations, you could inline the array:
//   string ingredient = x.FindAny("Salt", "Sugar", "Pepper");
if (ingredient != null)
{
    MessageBox.Show("The ingredient found in this line of myList is: " + ingredient);
}

Note: To output multiple ingredients found in the same line, use Where instead of FirstOrDefault:

string[] ingredients = { "Salt", "Sugar", "Pepper" };
foreach (string x in myList)
{
    List<string> ingredientsFound = ingredients.Where(x.Contains).ToList();
    if (ingredientsFound.Count > 0)
    {
        MessageBox.Show("The ingredient(s) found in this line of myList are: " +
            string.Join(", ", ingredientsFound));
    }
}

This is a simple way of doing this. Also, it prints all of the ingredients found to match a line.

I like Michael's solution, but knowing you can just do a simple i , j iteration on two arrays is essential.

string[] INGREDIENTS = {"Salt", "Sugar"};
foreach (string line in myList)
{
    foreach (string ingredient in INGREDIENTS)
    {   
        if (line.Contains(ingredient))
        {
            MessageBox.Show($"The ingredient found in this line of myList is: {ingredient}");
        }
    }
}

For a broader amount of possible ingredients, and reasonably small strings (but arbitrarily large number of them), using regex can show much better performance, as it doesn't have to iterate the string every time for all ingredients.

static readonly Regex ingredientRegex = new Regex("(Salt|Sugar|Pepper)", RegexOptions.Compiled | RegexOptions.CultureInvariant);
static void FindIngredient(string[] myList)
{
    foreach(string x in myList)
    {
        var match = ingredientRegex.Match(x);
        if(match.Success)
        {
            Console.WriteLine("The ingredient found in this line of myList is: " + match.Groups[1].Value);
        }
    }
}

Just remember to construct the Regex object beforehand.

The general solution to this sort of thing is to encapsulate it in your own function that you call. Michael Liu's answer might be preferable in the scenario where there are ways to do it with library functions. However if there weren't any you would do something like this:

bool ContainsAny(string haystack, IEnumerable<string> needles, out which)
{
    foreach(var s in needles)
    {
        if (haystack.Contains(s))
        {
            which = s;
            return true;
        }
    }
    which = null;
    return false;
}

And then just call that.

foreach (string x in myList)
{
     if (x.Contains("Salt") || x.Contains("Sugar") || x.Contains("Pepper"))
     {
         string s = "The ingredient found in this line of myList is: {0}", x;
         MessageBox.Show(s);
     }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM