Prueba si una cadena contiene alguna de las cadenas de una matriz


153

¿Cómo pruebo una cadena para ver si contiene alguna de las cadenas de una matriz?

En lugar de usar

if (string.contains(item1) || string.contains(item2) || string.contains(item3))

44
¿Pregunta si una cadena es igual a alguna de las cadenas de la matriz o si contiene alguna de las cadenas de la matriz?
Natix

1
¿Desea verificar si alguna cadena de la matriz es una subcadena de su cadena de entrada? ¿O desea verificar si su cadena de entrada es igual a una de la cadena en la matriz? puedes ser mas preciso?
Savino Sguera

1
contiene, para que tome una línea y vea si contiene alguna de las palabras de una lista (almacenada como una serie de cadenas)
arowell

Respuestas:


188

EDITAR: Aquí hay una actualización que usa la API Java 8 Streaming. Mucho más limpio. Todavía se puede combinar con expresiones regulares también.

public static boolean stringContainsItemFromList(String inputStr, String[] items) {
    return Arrays.stream(items).parallel().anyMatch(inputStr::contains);
}

Además, si cambiamos el tipo de entrada a una Lista en lugar de una matriz que podemos usar items.parallelStream().anyMatch(inputStr::contains).

También puede usar .filter(inputStr::contains).findAny()si desea devolver la cadena coincidente.


Respuesta original ligeramente anticuada:

Aquí hay un método estático (MUY BÁSICO). Tenga en cuenta que distingue entre mayúsculas y minúsculas en las cadenas de comparación. Una forma primitiva de hacer que no distinga entre mayúsculas y minúsculas sería llamar toLowerCase()o toUpperCase()en las cadenas de entrada y prueba.

Si necesita hacer algo más complicado que esto, le recomendaría que mire las clases de Patrón y Matcher y aprenda a hacer algunas expresiones regulares. Una vez que los comprenda, puede usar esas clases o el String.matches()método auxiliar.

public static boolean stringContainsItemFromList(String inputStr, String[] items)
{
    for(int i =0; i < items.length; i++)
    {
        if(inputStr.contains(items[i]))
        {
            return true;
        }
    }
    return false;
}

1
Cómo usarlo con expresión regular @gnomed
Praneeth

¿Cómo podemos hacer que la primera implementación distinga entre mayúsculas y minúsculas?
thanos.a

Las implementaciones ya distinguen entre mayúsculas y minúsculas. También tengo instrucciones sobre cómo hacer que no se distinga entre mayúsculas y minúsculas en los párrafos inferiores de la respuesta.
Gnomed

52
import org.apache.commons.lang.StringUtils;

Utilidades de cadena

Utilizar:

StringUtils.indexOfAny(inputString, new String[]{item1, item2, item3})

Devolverá el índice de la cadena encontrada o -1 si no se encuentra ninguno.


77
JFI: esperaba que esta implementación iterara solo una vez sobre inputString, pero miré el código en StringUtils, y lamentablemente solo hace N llamadas del indexOf predeterminado.
alfonx

¡Quizás en commons3 la implementación sea mejor!
renanleandrof

1
No, todavía solo itera sobre las cadenas en org.apache.commons.lang3.StringUtils: for (int i = 0; i <searchStrs.length; i ++) {CharSequenceUtils.indexOf (str, search, 0); ....
alfonx

Esto no devuelve el índice de la cadena encontrada (de la matriz), solo el índice de la posición en la que se encontró la cadena.
Plutón


16

La forma más fácil probablemente sería convertir la matriz en java.util.ArrayList. Una vez que se encuentra en una lista de arrays, puede aprovechar fácilmente el método contiene.

public static boolean bagOfWords(String str)
{
    String[] words = {"word1", "word2", "word3", "word4", "word5"};  
    return (Arrays.asList(words).contains(str));
}

70
Esto es incorrecto. OP pregunta si stringcontiene alguna Strings en la matriz, no si alguna Strings en la matriz contiene string.
Beau Grantham

3
@BeauGrantham También estaba pensando en esto, pero el OP lo está usando .equals()en su publicación, lo cual es muy confuso. Supongo que necesitan editar su pregunta
Recibió el

@BeauGrantham Man No podía jurar que entendía el problema. ¿Quizás la pregunta necesita aclararse un poco más?
Roy Kachouh

1
No, este tipo de dirección inversa no funcionará, debe verificar si String contiene UNO de los valores dados y NO si los valores dados contienen la cadena.
Vladimir Stazhilov

2
La pregunta es lo opuesto
Stéphane GRILLON

16

Si usa Java 8 o superior, puede confiar en Stream API para hacer lo siguiente:

public static boolean containsItemFromArray(String inputString, String[] items) {
    // Convert the array of String items as a Stream
    // For each element of the Stream call inputString.contains(element)
    // If you have any match returns true, false otherwise
    return Arrays.stream(items).anyMatch(inputString::contains);
}

Suponiendo que tiene una gran variedad de grandes Stringpara probar, también podría iniciar la búsqueda en paralelo llamando parallel(), el código sería:

return Arrays.stream(items).parallel().anyMatch(inputString::contains); 

Una cosa extraña que noté, tengo dos elementos en la lista de cadenas, descubrí que cuando uso 'paralelo' no devolverá los resultados correctos. (incluso si contiene el valor).
CharlesC

@ Charles.C eso es raro, no puedo reproducirlo de mi lado.
Nicolas Filotto

Estoy bastante seguro de que la paralelización de la secuencia sería subóptima aquí a menos que la cadena de entrada sea larga (~ 500 caracteres). En cambio, si la matriz era grande, probablemente sería mejor dividirla y ejecutar cada una de ellas en paralelo.
Lifesoordinary

2

Aquí hay una solución:

public static boolean containsAny(String str, String[] words)
{
   boolean bResult=false; // will be set, if any of the words are found
   //String[] words = {"word1", "word2", "word3", "word4", "word5"};

   List<String> list = Arrays.asList(words);
   for (String word: list ) {
       boolean bFound = str.contains(word);
       if (bFound) {bResult=bFound; break;}
   }
   return bResult;
}


1

Un enfoque más groovyesco sería usar inyectar en combinación con metaClass :

Me encantaría decir:

String myInput="This string is FORBIDDEN"
myInput.containsAny(["FORBIDDEN","NOT_ALLOWED"]) //=>true

Y el método sería:

myInput.metaClass.containsAny={List<String> notAllowedTerms->
   notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)})
}

Si necesita contieneAny para estar presente en cualquier variable de cadena futura, agregue el método a la clase en lugar del objeto:

String.metaClass.containsAny={notAllowedTerms->
   notAllowedTerms?.inject(false,{found,term->found || delegate.contains(term)})
}

1

Prueba esto:

if (Arrays.asList(item1, item2, item3).stream().anyMatch(string::contains))

15
La pregunta es lo contrario: ¿la cadena de destino contiene alguna de las cadenas de la lista?
Basil Bourque

1
La pregunta es lo contrario
Stéphane GRILLON

0

Y si está buscando una coincidencia entre mayúsculas y minúsculas, use el patrón

Pattern pattern = Pattern.compile("\\bitem1 |item2\\b",java.util.regex.Pattern.CASE_INSENSITIVE);

    Matcher matcher = pattern.matcher(input);
    if(matcher.find() ){ 

}

0

Si está buscando palabras completas , puede hacer esto que no distingue entre mayúsculas y minúsculas .

private boolean containsKeyword(String line, String[] keywords)
{
    String[] inputWords = line.split(" ");

    for (String inputWord : inputWords)
    {
        for (String keyword : keywords)
        {
            if (inputWord.equalsIgnoreCase(keyword))
            {
                return true;
            }
        }
    }

    return false;
}

0

También podemos hacer así:

if (string.matches("^.*?((?i)item1|item2|item3).*$"))
(?i): used for case insensitive
.*? & .*$: used for checking whether it is present anywhere in between the string.

-3

Lo siguiente debería funcionar para usted suponiendo que Strings es la matriz en la que está buscando:

Arrays.binarySearch(Strings,"mykeytosearch",mysearchComparator);

donde mykeytosearch es la cadena que desea probar para la existencia dentro de la matriz. mysearchComparator: es un comparador que se usaría para comparar cadenas.

Consulte Arrays.binarySearch para obtener más información.


2
Cabe señalar que binarySearch funciona solo en una matriz que está ordenada, ya sea de forma natural o por el comparador dado (si se proporciona).
Natix

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.