Teste se uma string contém alguma das strings de uma matriz

153

Como testar uma string para ver se ela contém alguma das strings de uma matriz?

Ao invés de usar

if (string.contains(item1) || string.contains(item2) || string.contains(item3))
arowell
fonte
4
Você está perguntando se uma string é igual a qualquer uma das strings da matriz ou contém alguma das strings da matriz?
Natix
1
Deseja verificar se alguma string da matriz é uma substring da sua string de entrada? Ou você deseja verificar se sua sequência de entrada é igual a uma sequência na matriz? Você pode ser mais preciso?
Savino Sguera
1
contém, para que ele leva uma linha e vê se ele contém qualquer uma das palavras de uma lista (armazenado como uma matriz de strings)
arowell

Respostas:

188

EDIT: Aqui está uma atualização usando o Java 8 Streaming API. Muito mais limpo. Ainda pode ser combinado com expressões regulares também.

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

Além disso, se alterarmos o tipo de entrada para uma lista em vez de uma matriz, podemos usar items.parallelStream().anyMatch(inputStr::contains).

Você também pode usar .filter(inputStr::contains).findAny()se desejar retornar a sequência correspondente.


Resposta original ligeiramente datada:

Aqui está um método estático (MUITO BÁSICO). Observe que diferencia maiúsculas de minúsculas nas seqüências de comparação. Uma maneira primitiva de diferenciar maiúsculas de minúsculas seria chamar toLowerCase()ou toUpperCase()nas cadeias de entrada e de teste.

Se você precisar fazer algo mais complicado do que isso, recomendo examinar as classes Pattern e Matcher e aprender a fazer algumas expressões regulares. Depois de entender essas, você pode usar essas classes ou o 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;
}
gnomed
fonte
1
Como usá-lo com expressão regular @gnomed
Praneeth
Como podemos diferenciar o primeiro caso de implementação?
thanos.a
As implementações já diferenciam maiúsculas de minúsculas. Também tenho instruções sobre como torná-lo sem distinção entre maiúsculas e minúsculas nos parágrafos inferiores da resposta.
gnomed
52
import org.apache.commons.lang.StringUtils;

Utilitários de String

Usar:

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

Ele retornará o índice da sequência encontrada ou -1 se nenhuma for encontrada.

renanleandrof
fonte
7
JFI: Eu esperava que essa implementação repetisse apenas uma vez sobre o inputString, mas observei o código no StringUtils e, infelizmente, ele está apenas fazendo N chamadas do indexOf padrão.
Alfonx
Talvez no commons3 a implementação seja melhor!
Renanleandrof 17/11/2015
1
Não, ainda apenas itera sobre as Strings em org.apache.commons.lang3.StringUtils: for (int i = 0; i <searchStrs.length; i ++) {CharSequenceUtils.indexOf (str, search, 0); ....
alfonx
Isso não retorna o índice da sequência encontrada (da matriz), apenas o índice da posição em que a sequência foi encontrada.
Plutão
33

Você pode usar o método String # corresponde assim:

System.out.printf("Matches - [%s]%n", string.matches("^.*?(item1|item2|item3).*$"));
anubhava
fonte
16

A maneira mais fácil provavelmente seria converter a matriz em um java.util.ArrayList. Uma vez em uma lista de matrizes, você pode facilmente aproveitar o método contains.

public static boolean bagOfWords(String str)
{
    String[] words = {"word1", "word2", "word3", "word4", "word5"};  
    return (Arrays.asList(words).contains(str));
}
Roy Kachouh
fonte
70
Isto está incorreto. OP está perguntando se stringcontém algum Strings na matriz, não se houver algum Strings na matriz string.
Beau Grantham
3
@BeauGrantham Eu também estava pensando nisso, mas o OP está usando .equals()no post deles, o que é muito confuso. Eu acho que eles precisam editar sua pergunta
gnomed
@BeauGrantham Cara, eu não podia jurar que entendi o problema. Talvez a questão precise ser esclarecida um pouco mais?
Roy Kachouh
1
Não, esse tipo de direção inversa não funcionará; verifique se String contém UM dos valores fornecidos e NOT se os valores fornecidos contêm a string.
Vladimir Stazhilov 18/08/16
2
A questão é o oposto #
Stéphane GRILLON 7/16/16
16

Se você usa o Java 8 ou superior, pode confiar na API Stream para fazer isso:

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

Supondo que você tenha uma grande variedade de coisas grandes Stringpara testar, você também pode iniciar a pesquisa em paralelo chamando parallel(), o código seria:

return Arrays.stream(items).parallel().anyMatch(inputString::contains); 
Nicolas Filotto
fonte
Uma coisa estranha que eu notei, eu tenho dois itens na lista String, eu descobri, quando eu uso 'paralelo', ele não retornará os resultados corretos. (mesmo que contenha o valor).
CharlesC
@ Charles.C é estranho, não consigo reproduzir do meu lado.
Nicolas Filotto
Eu tenho certeza que paralelizar o fluxo seria abaixo do ideal aqui, a menos que a string de entrada fosse longa (~ 500 caracteres). Em vez disso, se a matriz fosse grande, provavelmente seria melhor particionar a matriz e executar cada uma delas em paralelo.
lifesoordinary
2

Aqui está uma solução:

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

Desde a versão 3.4, o Apache Common Lang 3 implementa o método containsAny .

Arthur Vaïsse
fonte
Isso verifica a matriz Char
Saikat
1

Uma abordagem mais groovyesque seria usar injetar em combinação com metaClass :

Eu adoraria dizer:

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

E o método seria:

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

Se você precisar que o containsAny esteja presente para qualquer variável String futura, adicione o método à classe em vez do objeto:

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

Tente o seguinte:

if (Arrays.asList(item1, item2, item3).stream().anyMatch(string::contains))
Óscar López
fonte
15
A questão é o oposto: a string de destino contém alguma das strings da lista.
Basil Bourque 16/05
1
A questão é o oposto #
Stéphane GRILLON
0

E se você estiver procurando por correspondência sem distinção entre maiúsculas e minúsculas, use o padrão

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

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

}
vsingh
fonte
0

Se você busca palavras inteiras, pode fazer isso que não diferencia maiúsculas de 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;
}
thanos.a
fonte
0

Também podemos fazer assim:

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

O abaixo deve funcionar para você, assumindo que Strings é a matriz em que você está pesquisando:

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

onde mykeytosearch é a sequência que você deseja testar quanto à existência na matriz. mysearchComparator - é um comparador que seria usado para comparar strings.

Consulte Arrays.binarySearch para obter mais informações.

Prahalad Deshpande
fonte
2
Deve-se notar que o binarySearch funciona apenas em uma matriz classificada naturalmente ou pelo comparador fornecido (se for fornecido).
Natix
-4
if (Arrays.asList(array).contains(string))
Garrett Hall
fonte
10
A questão é o oposto: a string de destino contém alguma das strings da lista.
Basil Bourque 16/05
2
A questão é o oposto #
Stéphane GRILLON