如何检查字符串是否包含某些字符串


97

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

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

1
对于复杂的情况,请查找trie数据结构。
悲惨变量

Answers:


44

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

如果您想要任意字符串,那么我不知道.NET方法可以“直接”实现该功能,尽管可以使用正则表达式。


94

好吧,总有这样:

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");

但是,没有什么可以||比照您的比较链的性能了。


12
在这个不错的解决方案中添加新的简短语法 public static bool ContainsAny(this string haystack, params string[] needles) { return needles.Any(haystack.Contains); }
simonkaspers1

简单明了的解决方案。但是,有没有可以通过干草堆字符串进行多次迭代的,随时可以使用的良好实现?我可以自己实现它,遍历大海捞针字符串字符并一次比较顺序地比较针的第一个字符,但是我不敢相信在某些著名的NuGet库中尚未实现这种简单的解决方案。
RollerKostr

@RollerKostr它还没有内置在C#中(为什么),为什么要在您的项目中添加额外的依赖项以获得如此简单的解决方案?
jmdon

70

这是一个LINQ解决方案,它实际上是相同的,但可扩展性更高:

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

3
从可轻松添加字符而不是从性能的角度来说,这是可扩展的... :)
Guffa 2010年

2
是的,当然。也许“更可扩展”将是更好的词语选择。
杰夫·梅卡多

表演不会很糟糕。无论如何,比解释的正则表达式更好。
史蒂文·

出于完整性的考虑,您可以先将传入的字符串拆分为一个数组,例如:var splitStringArray = someString.Split(''); 然后,您可以执行以下操作:if(someStringArray.Any(s => otherString.Contains(s))){//做某事}希望可以帮助某人变得清晰。
塔希尔·哈立德

45
var values = new [] {"abc", "def", "ghj"};
var str = "abcedasdkljre";
values.Any(str.Contains);

21

您可以尝试使用正则表达式

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

1
+1,尽管由于他正在寻找单个字符,所以linq解决方案或indexOfAny可能会更有效。
Joel Coehoorn

+1为正则表达式。如果没有IndexOfAny
Stavros,2010年

1
正则表达式对此过于矫kill过正。
史蒂文·苏迪特

3
是什么使人们说正则表达式对此有过大的杀伤力?如果正则表达式只编译一次并使用多次,并且您的字符串中只有c或在开头附近有c,在结尾处有a,b的字符串,则该regex效率会高得多。
bruceboughton 2010年

它不适用于特殊字符--''。`=
MAFAIZ

14

如果您需要包含特定值的ContainsAny StringComparison(例如,忽略大小写),则可以使用此String Extensions方法。

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.

2
只需一个注释即可改善此答案。您可以使用params关键字将它写得更加细腻:ContainsAny(此字符串输入,StringComparison comparisonType,params字符串[] containsKeywords),并使用类似input.ContainsAny(substrings,StringComparison.CurrentCultureIgnoreCase,“ string”,“ many substrings” ...等等)
罗玛·波罗多夫

7

这是“更精细的解决方案”,非常简单

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

4

由于字符串是字符的集合,因此可以在它们上使用LINQ扩展方法:

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

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

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

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

同意 当第一个条件不匹配时,这解决了多次扫描的问题。想知道lambda的开销是多少吗?虽然不应该太多。
bruceboughton 2010年

3
public static bool ContainsAny(this string haystack, IEnumerable<string> needles)
{
    return needles.Any(haystack.Contains);
}

3
List<string> includedWords = new List<string>() { "a", "b", "c" };
bool string_contains_words = includedWords.Exists(o => s.Contains(o));

2
// 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为每


2
    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;
    }

1
HasWantedCharacters方法接受两个或三个字符串。我们要检查某些字符的第一个字符串。第二个字符串,我们将在第一个字符串中查找的所有字符。重载方法将输出作为第三个字符串提供给调用方(即Main)。嵌套的foreach语句遍历源代码中的每个字符,并将其一个一个地比较。我们正在检查的那些字符。如果找到其中一个字符,则返回true。重载的方法输出找到的字符串与所检查的字符匹配,但直到所有字符都消失后才会返回。有帮助吗?
内特·威尔金斯

1
随意启动C#控制台项目并在程序类中复制代码-请务必替换main方法。修改这两个字符串(goodUserName和badUserName),您可能会看到这些方法做什么以及它们如何工作。这些示例较长,以提供一种可行的解决方案,无需使用逗号等分隔符即可对其进行修改。如果需要检查转义序列,它只是表示单引号和反斜杠的一种方式。
内特·威尔金斯


0

如果您要查找任意字符串,而不仅仅是字符,则可以使用IndexOfAny的重载,该重载从新项目NLib中获取字符串参数:

if (s.IndexOfAny("aaa", "bbb", "ccc", StringComparison.Ordinal) >= 0)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.