Verifica se una stringa contiene una qualsiasi delle stringhe di un array


153

Come testare una stringa per vedere se contiene una delle stringhe di un array?

Invece di usare

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

4
Stai chiedendo se una stringa è uguale a una qualsiasi delle stringhe nell'array o contiene una qualsiasi delle stringhe dell'array?
Natix,

1
Vuoi verificare se una stringa dell'array è una sottostringa della stringa di input? Oppure vuoi verificare se la tua stringa di input è uguale a una delle stringhe nell'array? Puoi essere più preciso?
Savino Sguera,

1
contiene, in modo da prendere una riga e vedere se contiene una delle parole di un elenco (memorizzato come una matrice di stringhe)
arowell

Risposte:


189

EDIT: ecco un aggiornamento usando l'API Streaming Java 8. Molto più pulito. Può ancora essere combinato anche con espressioni regolari.

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

Inoltre, se cambiamo il tipo di input in un Elenco anziché in un array, possiamo usarlo items.parallelStream().anyMatch(inputStr::contains).

È inoltre possibile utilizzare .filter(inputStr::contains).findAny()se si desidera restituire la stringa corrispondente.


Risposta originale leggermente datata:

Ecco un metodo statico (MOLTO BASE). Si noti che è sensibile al maiuscolo / minuscolo sulle stringhe di confronto. Un modo primitivo per rendere maiuscole e minuscole sarebbe quello di chiamare toLowerCase()o toUpperCase()su entrambe le stringhe di input e test.

Se hai bisogno di fare qualcosa di più complicato di questo, consiglierei di guardare le classi Pattern e Matcher e imparare come fare alcune espressioni regolari. Una volta che li capisci, puoi usare quelle classi o il String.matches()metodo helper.

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
Come usarlo con espressione regolare @gnomed
Praneeth

Come possiamo rendere sensibile il primo caso di implementazione?
thanos.a

Le implementazioni sono già sensibili al maiuscolo / minuscolo. Ho anche istruzioni su come renderlo maiuscole e minuscole nei paragrafi inferiori della risposta.
Gnomed,

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

Utensili a corda

Uso:

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

Restituirà l'indice della stringa trovata o -1 se non viene trovata alcuna.


7
JFI: Speravo che questa implementazione potesse iterare solo una volta su inputString, ma ho guardato il codice in StringUtils, e purtroppo sta facendo solo N chiamate dell'indiceOf predefinito.
alfonx,

Forse su commons3 l'implementazione è migliore!
renanleandrof,

1
No, continua a ripetere le stringhe in org.apache.commons.lang3.StringUtils: for (int i = 0; i <searchStrs.length; i ++) {CharSequenceUtils.indexOf (str, search, 0); ....
alfonx,

Ciò non restituisce l'indice della stringa trovata (dall'array), ma solo l'indice della posizione in cui è stata trovata la stringa.
Plutone,

33

È possibile utilizzare il metodo Match # string in questo modo:

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

16

Il modo più semplice sarebbe probabilmente convertire l'array in un file java.util.ArrayList. Una volta che è in un arraylist, puoi facilmente sfruttare il metodo contenute.

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

70
Questo non è corretto OP chiede se stringcontiene qualche Strings nell'array, non se contiene alcun s Stringnell'array string.
Beau Grantham,

3
@BeauGrantham Stavo pensando anche a questo, ma l'OP sta usando .equals()nel loro post, il che è molto confuso. Immagino che debbano modificare la loro domanda
gnomed il

@BeauGrantham Man non potevo giurare di aver capito il problema. Forse la domanda deve essere chiarita un po 'di più?
Roy Kachouh,

1
No, questo tipo di direzione inversa non funzionerà, è necessario verificare se String contiene UNO dei valori indicati e NON se i valori forniti contengono la stringa.
Vladimir Stazhilov,

2
La domanda è l'opposto
Stéphane GRILLON il

16

Se usi Java 8 o versioni successive, puoi fare affidamento sull'API Stream per fare ciò:

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

Supponendo che tu abbia una vasta gamma di grandi Stringda testare, potresti anche avviare la ricerca in parallelo chiamando parallel(), il codice sarebbe quindi:

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

Una cosa strana che ho notato, ho due elementi nell'elenco String, ho scoperto, quando uso 'parallel' non restituirà i risultati corretti. (anche se contiene il valore).
CharlesC,

@ Charles.C è strano che non riesco a riprodurre dalla mia parte.
Nicolas Filotto,

Sono abbastanza sicuro che parallelizzare il flusso non sarebbe ottimale qui a meno che la stringa di input non fosse lunga (~ 500 caratteri). Invece, se l'array fosse grande, sarebbe probabilmente meglio partizionare l'array ed eseguirne uno in parallelo.
straordinario

2

Ecco una soluzione:

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 approccio più groovyesque sarebbe usare iniettare in combinazione con metaClass :

Mi piacerebbe dire:

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

E il metodo sarebbe:

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

Se hai bisogno di contieneAny per essere presente per qualsiasi futura variabile String, aggiungi il metodo alla classe anziché all'oggetto:

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


0

E se stai cercando una corrispondenza senza distinzione tra maiuscole e minuscole, usa il modello

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

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

}

0

Se stai cercando parole intere , puoi farlo senza distinzione tra maiuscole e minuscole .

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

Possiamo anche fare così:

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

Di seguito dovrebbe funzionare per te supponendo che Strings sia l'array in cui stai cercando:

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

dove mykeytosearch è la stringa che si desidera verificare l'esistenza all'interno dell'array. mysearchComparator - è un comparatore che verrebbe utilizzato per confrontare le stringhe.

Fare riferimento a Arrays.binarySearch per ulteriori informazioni.


2
Va notato che binarySearch funziona solo su array ordinati, in modo naturale o dal dato comparatore (se fornito).
Natix,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.