2010-08-19 9 views

Respuesta

31

Si está buscando caracteres individuales, puede utilizar String.IndexOfAny().

Si quieres cadenas arbitrarias, entonces no estoy al tanto de un método .NET para lograr que "directamente", aunque una expresión regular funcionaría.

62

Bueno, siempre hay presente:

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

    return false; 
} 

Uso:

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

Nada va a coincidir con el rendimiento de su cadena de || comparaciones, sin embargo.

+1

1 para la solución general – Stavros

+3

Adición de una nueva sintaxis corta a esta solución agradable 'public static bool ContainsAny (esta cadena pajar, params cadena agujas []) { retorno needles.Any (haystack.Contains); } ' – simonkaspers1

19

Usted puede tratar con expresiones regulares

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

+1, aunque como está buscando caracteres únicos, una solución linq o indexOfAny podría ser más eficiente. –

+0

+1 para la expresión regular. eso es lo que habría elegido, si no hubiera IndexOfAny – Stavros

+1

Las expresiones regulares son excesivas para esto. –

1

Puede utilizar Regular Expressions

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

Sin duda puedes, pero no veo por qué querrías cuando casi todo lo demás es mejor. –

37

he aquí una solución LINQ que es prácticamente lo mismo pero más escalable:

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

Eso es escalable en el sentido de que es fácil agregar caracteres, no en el sentido de rendimiento ... :) – Guffa

+1

Ah sí, por supuesto. Tal vez "más extensible" habría sido una mejor opción de palabras. –

+0

El rendimiento no será terrible. Mejor que una expresión regular interpretada, de todos modos. –

3

Como cadena es un conjunto de caracteres, puede utilizar los métodos de extensión de LINQ en ellos:

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

Este Escaneará la cadena una vez y se detendrá en la primera aparición, en lugar de escanear la cadena una vez por cada carácter hasta que se encuentre una coincidencia.

Esto también puede ser utilizado para cualquier expresión que te gusta, por ejemplo, la comprobación de una serie de caracteres:

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

De acuerdo. Esto resuelve el problema de los escaneos múltiples cuando las primeras condiciones no coinciden. Me pregunto qué es la sobrecarga de la lambda. Sin embargo, no debería ser mucho una vez. – 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 para cualquier, All para cada

0

Si está buscando para cadenas arbitrarias, y no sólo los caracteres, puede utilizar una sobrecarga de IndexOfAny que tiene argumentos de cadena del nuevo proyecto NLib:

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

Ese enlace ya no funciona. –

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

tomar mi marca positiva funciona ... – Steve

4

Esta es una "solución más agradable" y bastante simple

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

Si necesita ContainsAny con una específica StringComparison (por ejemplo, hacer caso omiso de los casos), puede utilizar este método Extensiones de Cuerda.

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

uso con 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

Solo una nota para mejorar esta respuesta. Se puede escribir aún más ellegant con la palabra clave params: ContainsAny (esta entrada de cadena, StringComparison comparisonType, cadena params [] containsKeywords) y utilizar como input.ContainsAny (subseries, StringComparison.CurrentCultureIgnoreCase, "cadena", "muchas subcadenas" ... 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

Puede explicar su código –

+1

Los métodos HasWantedCharacters aceptan dos o tres cadenas. La primera cadena que queremos verificar para ciertos caracteres. La segunda cadena, todos los personajes que buscaremos en la primera. El método sobrecargado proporciona salida a la persona que llama (es decir, Main) como una tercera cadena. Una instrucción foreach anidada recorre cada carácter en el origen y lo compara, uno por uno; con esos personajes que estamos buscando. Si se encuentra uno de los caracteres, devuelve verdadero. El método sobrecargado genera una cadena de caracteres encontrados que coinciden con los marcados, pero no volverán hasta que todos estén fuera. ¿Servicial? –

+1

Siéntase libre de iniciar un proyecto de consola C# y copiar el código dentro de la clase del programa; asegúrese de reemplazar el método principal. Juega con las dos cadenas (goodUserName y badUserName) y es posible que veas qué hacen los métodos y cómo funcionan. Los ejemplos son más largos para proporcionar una solución viable que se puede modificar sin delimitadores como comas. Las secuencias de escape son solo una forma de representar la comilla simple y la barra diagonal inversa si necesita verificarlas. –

Cuestiones relacionadas