2010-08-19 25 views

Antwort

31

Wenn Sie für einzelne Zeichen suchen können, können Sie String.IndexOfAny() verwenden.

Wenn Sie beliebige Strings wollen, dann ist mir keine .NET-Methode bekannt, um das "direkt" zu erreichen, obwohl ein regulärer Ausdruck funktionieren würde.

62

Nun, es gibt immer:

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

    return false; 
} 

Verbrauch:

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

Nichts wird die Leistung Ihrer Kette von || anzupassen Vergleiche jedoch.

+1

+1 für die allgemeine Lösung – Stavros

+3

Hinzufügen einer neuen kurzen Syntax zu dieser netten Lösung 'öffentliche statische Bool ContainsAny (diese Zeichenfolge Heuhaufen, Parameter String [] Nadeln) { zurück Nadeln.Any (Heuhaufen.Kontakt); } ' – simonkaspers1

19

Sie können mit regulären Ausdrücken versuchen

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

+1, obwohl, da er nach einzelnen Zeichen sucht, eine linq Lösung oder indexOfAny effizienter sein könnte. –

+0

+1 für den regulären Ausdruck. das wäre, wofür ich hingehen würde, wenn es nicht IndexOfAny – Stavros

+1

Reguläre Ausdrücke sind übertrieben dafür. –

1

Sie Regular Expressions

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

Das können Sie sicherlich, aber ich sehe nicht, warum Sie wollen, wenn fast alles andere besser ist. –

37

Hier ist eine LINQ-Lösung, die praktisch die gleiche ist, aber besser skalierbar:

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

Das ist skalierbar in dem Sinne, dass es einfach ist, Zeichen hinzuzufügen, nicht im Sinne von Leistung ... :) – Guffa

+1

Ah ja, natürlich. Vielleicht wäre "erweiterbar" eine bessere Wortwahl gewesen. –

+0

Die Leistung wird nicht schrecklich sein. Jedenfalls besser als eine interpretierte Regexp. –

3

Als Zeichenfolge ist eine Sammlung von Zeichen, können Sie LINQ-Erweiterungsmethoden auf sie verwenden:

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

Diese scannt die Zeichenfolge einmal und stoppt beim ersten Auftreten, anstatt die Zeichenfolge für jedes Zeichen einmal zu scannen, bis eine Übereinstimmung gefunden wird.

Dies kann auch für jeden Ausdruck verwendet werden, die Sie mögen, zum Beispiel für eine Reihe von Zeichen Überprüfung:

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

Einverstanden. Dies behebt das Problem mehrerer Scans, wenn die ersten Bedingungen nicht übereinstimmen. Frage mich, was der Overhead des Lambda ist? Sollte einmal nicht viel sein. – bruceboughton

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 für alle, All für jeden

0

Wenn Sie schauen, Für beliebige Zeichenfolgen und nicht nur für Zeichen können Sie eine Überladung von IndexOfAny verwenden, die Zeichenfolgenargumente aus dem neuen Projekt NLib:

übernimmt
if (s.IndexOfAny("aaa", "bbb", "ccc", StringComparison.Ordinal) >= 0) 
+0

Dieser Link funktioniert nicht mehr. –

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

nimm meine Marke, es funktioniert ... – Steve

4

Dies ist eine „schönere Lösung“ und ganz einfach

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

Wenn Sie ContainsAny mit einem spezifischen StringComparison (zB Fall zu ignorieren) benötigen, dann können Sie diesen String Extentions Methode verwenden.

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

Verwendung mit StringComparison.CurrentCultureIgnoreCase:

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

”xyz”.ContainsAny(substrings, StringComparison.CurrentCultureIgnoreCase); 
// This statement returns false. 
+1

Nur eine Notiz, um diese Antwort zu verbessern. Man könnte schreiben es noch ellegant mit params Stichwort: ContainsAny (dieser String-Eingang, StringComparison comparisonType, params string [] containsKeywords) und verwenden wie input.ContainsAny (Substrings, StringComparison.CurrentCultureIgnoreCase, "string", "viele Teilstrings" ... etc) –

3
public static bool ContainsAny(this string haystack, IEnumerable<string> needles) 
{ 
    return needles.Any(haystack.Contains); 
} 
2
List<string> includedWords = new List<string>() { "a", "b", "c" }; 
bool string_contains_words = includedWords.Exists(o => s.Contains(o)); 
1
static void Main(string[] args) 
    { 
     string illegalCharacters = "[email protected]#$%^&*()\\/{}|<>,.~`?"; //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; 
    } 
+0

Können Sie Ihren Code erklären –

+1

Die Methoden HasWantedCharacters akzeptieren zwei oder drei Zeichenfolgen. Die erste Zeichenfolge, die wir auf bestimmte Zeichen überprüfen möchten. Die zweite Zeichenfolge, alle Zeichen, nach denen wir in der ersten suchen werden. Die überladene Methode liefert die Ausgabe an den Aufrufer (dh Main) als eine dritte Zeichenfolge. Eine verschachtelte foreach-Anweisung durchläuft jedes Zeichen in der Quelle und vergleicht es einzeln. mit den Charakteren, nach denen wir suchen. Wenn eines der Zeichen gefunden wird, wird True zurückgegeben. Die überladene Methode gibt eine Zeichenkette aus, die mit den gefundenen Zeichen übereinstimmt, aber nicht zurückkehrt, bis alle aus sind. Hilfreich? –

+1

Fühlen Sie sich frei, ein C# -Konsolenprojekt zu starten und den Code innerhalb der Programmklasse zu kopieren - stellen Sie sicher, dass Sie die Hauptmethode ersetzen. Tinker mit den zwei Zeichenfolgen (goodUserName und badUserName) und Sie können sehen, was die Methoden tun und wie sie funktionieren. Die Beispiele sind länger, um eine praktikable Lösung bereitzustellen, die ohne Trennzeichen wie Kommas modifiziert werden kann. Escape-Sequenzen sind nur eine Möglichkeit, das einfache Anführungszeichen und den umgekehrten Schrägstrich darzustellen, wenn Sie nach ihnen suchen müssen. –

Verwandte Themen