【问题标题】:How to check if a String contains any of some strings如何检查字符串是否包含某些字符串
【发布时间】:2011-03-31 23:27:37
【问题描述】:

我想检查 C# 中的 String s 是否包含“a”或“b”或“c”。 我正在寻找比使用更好的解决方案

if (s.contains("a")||s.contains("b")||s.contains("c"))

【问题讨论】:

  • 对于复杂的情况,请查阅trie数据结构。

标签: c# string contains


【解决方案1】:

嗯,总是这样:

public static bool ContainsAny(this string haystack, params string[] needles)
{
    foreach (string needle in needles)
    {
        if (haystack.Contains(needle))
            return true;
    }

    return false;
}

用法:

bool anyLuck = s.ContainsAny("a", "b", "c");

然而,没有什么能比得上|| 比较链的性能。

【讨论】:

  • 为这个不错的解决方案添加新的短语法public static bool ContainsAny(this string haystack, params string[] needles) { return needles.Any(haystack.Contains); }
  • 简单明了的解决方案。但是,是否有任何无需通过 haystack 字符串进行多次迭代的现成可用的实现?我可以自己实现它,遍历 haystack 字符串字符并一次按顺序比较针的第一个字符,但我不敢相信这种微不足道的解决方案还没有在一些著名的 NuGet 库中实现。
  • @RollerKostr 它还没有内置到 C# 中(还),那么为什么要在你的项目中添加额外的依赖项来实现这样一个简单的解决方案呢?
  • 就是这样。谨记案例!你们可能想在“双方”上应用 ToUpperInvariant()
【解决方案2】:

这是一个几乎相同但更具可扩展性的 LINQ 解决方案:

new[] { "a", "b", "c" }.Any(c => s.Contains(c))

【讨论】:

  • 这是可扩展的,因为它很容易添加字符,而不是性能...... :)
  • 啊,是的,当然。也许“更可扩展”会是更好的词选择。
  • 性能不会很差。无论如何,比解释的正则表达式更好。
  • 为了完整性,您可以先将传入的字符串拆分为一个数组,例如: var splitStringArray = someString.Split(' ');然后你可以做类似的事情: if(someStringArray.Any(s => otherString.Contains(s))) { // 做一些事情 } 希望能帮助某人清楚。
【解决方案3】:
var values = new [] {"abc", "def", "ghj"};
var str = "abcedasdkljre";
values.Any(str.Contains);

【讨论】:

  • 这很优雅!谢谢!
【解决方案4】:

如果要查找单个字符,可以使用String.IndexOfAny()。

如果你想要任意字符串,那么我不知道有一种 .NET 方法可以“直接”实现这一点,尽管正则表达式可以工作。

【讨论】:

    【解决方案5】:

    你可以试试正则表达式

    string s;
    Regex r = new Regex ("a|b|c");
    bool containsAny = r.IsMatch (s);
    

    【讨论】:

    • +1,但由于他正在寻找单个字符,因此 linq 解决方案或 indexOfAny 可能更有效。
    • +1 表示正则表达式。如果没有 IndexOfAny,这就是我的目标
    • 正则表达式对此太过分了。
    • 是什么让人们说正则表达式为此过分?如果正则表达式编译一次并多次使用,并且您的字符串中只有 c 或 c 靠近开头而 a、b 靠近结尾,则正则表达式会更有效率。
    • 它不适用于特殊字符,例如 - , ' " . ` =
    【解决方案6】:

    如果您需要具有特定 StringComparison 的 ContainsAny(例如忽略大小写),则可以使用此字符串扩展方法。

    public static class StringExtensions
    {
        public static bool ContainsAny(this string input, IEnumerable<string> containsKeywords, StringComparison comparisonType)
        {
            return containsKeywords.Any(keyword => input.IndexOf(keyword, comparisonType) >= 0);
        }
    }
    

    与StringComparison.CurrentCultureIgnoreCase一起使用:

    var input = "My STRING contains Many Substrings";
    var substrings = new[] {"string", "many substrings", "not containing this string" };
    input.ContainsAny(substrings, StringComparison.CurrentCultureIgnoreCase);
    // The statement above returns true.
    
    ”xyz”.ContainsAny(substrings, StringComparison.CurrentCultureIgnoreCase);
    // This statement returns false.
    

    【讨论】:

    • 只需一个注释即可改进此答案。你可以用 params 关键字写得更优雅: ContainsAny(this string input, StringComparison comparisonType, params string [] containsKeywords) 并使用 like input.ContainsAny(substrings, StringComparison.CurrentCultureIgnoreCase, "string", "many substrings"...等)
    【解决方案7】:

    这是一个“更好的解决方案”而且非常简单

    if(new string[] { "A", "B", ... }.Any(s=>myString.Contains(s)))
    

    【讨论】:

      【解决方案8】:
      List<string> includedWords = new List<string>() { "a", "b", "c" };
      bool string_contains_words = includedWords.Exists(o => s.Contains(o));
      

      【讨论】:

        【解决方案9】:
        public static bool ContainsAny(this string haystack, IEnumerable<string> needles)
        {
            return needles.Any(haystack.Contains);
        }
        

        【讨论】:

          【解决方案10】:

          由于字符串是字符的集合,您可以对它们使用 LINQ 扩展方法:

          if (s.Any(c => c == 'a' || c == 'b' || c == 'c')) ...
          

          这将扫描字符串一次并在第一次出现时停止,而不是为每个字符扫描一次字符串直到找到匹配项。

          这也可以用于您喜欢的任何表达式,例如检查字符范围:

          if (s.Any(c => c >= 'a' && c <= 'c')) ...
          

          【讨论】:

          • 同意。这解决了第一个条件不匹配时多次扫描的问题。想知道 lambda 的开销是多少?不过一次应该不会太多。
          【解决方案11】:
          // Nice method's name, @Dan Tao
          
          public static bool ContainsAny(this string value, params string[] params)
          {
              return params.Any(p => value.Compare(p) > 0);
              // or
              return params.Any(p => value.Contains(p));
          }
          

          Any 表示任何一个,All 表示每个

          【讨论】:

            【解决方案12】:
                static void Main(string[] args)
                {
                    string illegalCharacters = "!@#$%^&*()\\/{}|<>,.~`?"; //We'll call these the bad guys
                    string goodUserName = "John Wesson";                   //This is a good guy. We know it. We can see it!
                                                                           //But what if we want the program to make sure?
                    string badUserName = "*_Wesson*_John!?";                //We can see this has one of the bad guys. Underscores not restricted.
            
                    Console.WriteLine("goodUserName " + goodUserName +
                        (!HasWantedCharacters(goodUserName, illegalCharacters) ?
                        " contains no illegal characters and is valid" :      //This line is the expected result
                        " contains one or more illegal characters and is invalid"));
                    string captured = "";
                    Console.WriteLine("badUserName " + badUserName +
                        (!HasWantedCharacters(badUserName, illegalCharacters, out captured) ?
                        " contains no illegal characters and is valid" :
                        //We can expect this line to print and show us the bad ones
                        " is invalid and contains the following illegal characters: " + captured));  
            
                }
            
                //Takes a string to check for the presence of one or more of the wanted characters within a string
                //As soon as one of the wanted characters is encountered, return true
                //This is useful if a character is required, but NOT if a specific frequency is needed
                //ie. you wouldn't use this to validate an email address
                //but could use it to make sure a username is only alphanumeric
                static bool HasWantedCharacters(string source, string wantedCharacters)
                {
                    foreach(char s in source) //One by one, loop through the characters in source
                    {
                        foreach(char c in wantedCharacters) //One by one, loop through the wanted characters
                        {
                            if (c == s)  //Is the current illegalChar here in the string?
                                return true;
                        }
                    }
                    return false;
                }
            
                //Overloaded version of HasWantedCharacters
                //Checks to see if any one of the wantedCharacters is contained within the source string
                //string source ~ String to test
                //string wantedCharacters ~ string of characters to check for
                static bool HasWantedCharacters(string source, string wantedCharacters, out string capturedCharacters)
                {
                    capturedCharacters = ""; //Haven't found any wanted characters yet
            
                    foreach(char s in source)
                    {
                        foreach(char c in wantedCharacters) //Is the current illegalChar here in the string?
                        {
                            if(c == s)
                            {
                                if(!capturedCharacters.Contains(c.ToString()))
                                    capturedCharacters += c.ToString();  //Send these characters to whoever's asking
                            }
                        }
                    }
            
                    if (capturedCharacters.Length > 0)  
                        return true;
                    else
                        return false;
                }
            

            【讨论】:

            • HasWantedCharacters 方法接受两个或三个字符串。我们要检查某些字符的第一个字符串。第二个字符串,我们将在第一个中查找的所有字符。重载方法将输出作为第三个字符串提供给调用者(即 Main)。嵌套的 foreach 语句遍历源中的每个字符并逐个比较它;使用我们正在检查的那些字符。如果找到其中一个字符,则返回 true。重载的方法输出一串与检查的字符匹配的字符串,但在所有字符都用完之前不会返回。有用吗?
            • 随意启动一个C#控制台项目,复制程序类里面的代码——一定要替换掉main方法。修改两个字符串(goodUserName 和 badUserName),您可能会看到这些方法的作用和工作方式。这些示例更长,以便提供一个可行的解决方案,该解决方案可以在没有逗号等分隔符的情况下进行修改。如果您需要检查它们,转义序列只是表示单引号和反斜杠的一种方式。
            【解决方案13】:

            您可以使用Regular Expressions

            if(System.Text.RegularExpressions.IsMatch("a|b|c"))
            

            【讨论】:

            • 你当然可以,但我不明白为什么你会想要几乎其他任何东西都更好。
            【解决方案14】:

            你可以为你的扩展方法创建一个类并添加这个:

                public static bool Contains<T>(this string s, List<T> list)
                {
                    foreach (char c in s)
                    {
                        foreach (T value in list)
                        {
                            if (c == Convert.ToChar(value))
                                return true;
                        }
                    }
                    return false;
                }
            

            【讨论】:

              【解决方案15】:

              如果这是一个有要求的密码检查器,试试这个:

              public static bool PasswordChecker(string input)
              {
                  // determins if a password is save enough
                  if (input.Length < 8)
                      return false;
              
                  if (!new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
                                      "S", "T", "U", "V", "W", "X", "Y", "Z", "Ä", "Ü", "Ö"}.Any(s => input.Contains(s)))
                  return false;
              
                  if (!new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}.Any(s => input.Contains(s)))
                  return false;
              
                  if (!new string[] { "!", "'", "§", "$", "%", "&", "/", "(", ")", "=", "?", "*", "#", "+", "-", "_", ".",
                                      ",", ";", ":", "`", "´", "^", "°",   }.Any(s => input.Contains(s)))
                  return false;
              
                  return true; 
              }
              

              这将设置密码的最小长度为 8,让它使用至少一个大写字符、至少一个数字和至少一个特殊字符

              【讨论】:

                猜你喜欢
                • 2016-08-09
                • 2014-05-07
                • 2019-12-29
                • 2018-05-01
                • 2015-03-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多