Teste si une chaîne contient l'une des chaînes d'un tableau

153

Comment tester une chaîne pour voir si elle contient l'une des chaînes d'un tableau?

À la place d'utiliser

if (string.contains(item1) || string.contains(item2) || string.contains(item3))
à droite
la source
4
Demandez-vous si une chaîne est égale à l'une des chaînes du tableau ou contient l' une des chaînes du tableau?
Natix
1
Vous voulez vérifier si une chaîne du tableau est une sous-chaîne de votre chaîne d'entrée? Ou vous voulez vérifier si votre chaîne d'entrée est égale à l' une des chaînes du tableau? Pouvez-vous être plus précis?
Savino Sguera
1
contient, de sorte qu'il prenne une ligne et voit s'il contient l'un des mots d'une liste (stocké sous forme de tableau de chaînes)
arowell

Réponses:

189

EDIT: Voici une mise à jour utilisant l'API Java 8 Streaming. Tellement plus propre. Peut également être combiné avec des expressions régulières.

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

De plus, si nous changeons le type d'entrée en List au lieu d'un tableau, nous pouvons utiliser items.parallelStream().anyMatch(inputStr::contains).

Vous pouvez également utiliser .filter(inputStr::contains).findAny()si vous souhaitez renvoyer la chaîne correspondante.


Réponse originale légèrement datée:

Voici une méthode statique (TRÈS BASIQUE). Notez qu'il est sensible à la casse sur les chaînes de comparaison. Une façon primitive de le rendre insensible à la casse serait d'appeler toLowerCase()ou toUpperCase()à la fois sur les chaînes d'entrée et de test.

Si vous avez besoin de faire quelque chose de plus compliqué que cela, je vous recommande de regarder les classes Pattern et Matcher et d'apprendre à faire des expressions régulières. Une fois que vous les avez compris, vous pouvez utiliser ces classes ou la String.matches()méthode d'assistance.

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
la source
1
Comment l'utiliser avec une expression régulière @gnomed
Praneeth
Comment rendre la première implémentation sensible à la casse?
thanos.a
Les implémentations sont déjà sensibles à la casse. J'ai également des instructions sur la façon de le rendre insensible à la casse dans les paragraphes inférieurs de la réponse.
gnomed
52
import org.apache.commons.lang.StringUtils;

Utils de chaîne

Utilisation:

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

Il renverra l'index de la chaîne trouvée ou -1 si aucun n'est trouvé.

renanleandrof
la source
7
JFI: J'espérais que cette implémentation n'itérerait qu'une seule fois sur inputString, mais j'ai regardé le code dans StringUtils, et malheureusement, il ne fait que N appels de l'indexOf par défaut.
alfonx
Peut-être que sur commons3, la mise en œuvre est meilleure!
renanleandrof
1
Non, répète simplement les chaînes dans org.apache.commons.lang3.StringUtils: for (int i = 0; i <searchStrs.length; i ++) {CharSequenceUtils.indexOf (str, search, 0); ....
alfonx
Cela ne renvoie pas l'index de la chaîne trouvée (à partir du tableau), seul l'index de la position à laquelle la chaîne a été trouvée.
Pluton le
33

Vous pouvez utiliser la méthode String # matches comme ceci:

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

Le moyen le plus simple serait probablement de convertir le tableau en java.util.ArrayList. Une fois qu'il est dans une arraylist, vous pouvez facilement utiliser la méthode contains.

public static boolean bagOfWords(String str)
{
    String[] words = {"word1", "word2", "word3", "word4", "word5"};  
    return (Arrays.asList(words).contains(str));
}
Roy Kachouh
la source
70
Ceci est une erreur. OP demande si stringcontient des Strings dans le tableau, pas si des Strings dans le tableau contiennent string.
Beau Grantham
3
@BeauGrantham Je pensais cela aussi, mais l'OP utilise .equals()dans leur message, ce qui est très déroutant. Je pense qu'ils doivent modifier leur question
gnomed
@BeauGrantham Man Je n'ai pas pu jurer que j'avais compris le problème. Peut-être que la question doit être clarifiée un peu plus?
Roy Kachouh
1
Non, ce type de direction inverse ne fonctionnera pas, vous devriez vérifier si String contient UNE des valeurs données et NON si les valeurs données contiennent la chaîne.
Vladimir Stazhilov
2
La question est le contraire
Stéphane GRILLON
16

Si vous utilisez Java 8 ou supérieur, vous pouvez compter sur l' API Stream pour faire une telle chose:

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

En supposant que vous ayez un grand tableau de big Stringà tester, vous pouvez également lancer la recherche en parallèle en appelant parallel(), le code serait alors:

return Arrays.stream(items).parallel().anyMatch(inputString::contains); 
Nicolas Filotto
la source
Une chose étrange que j'ai remarquée, j'ai deux éléments dans la liste des chaînes, j'ai découvert que lorsque j'utilise `` parallèle '', cela ne renvoie pas les bons résultats. (même s'il contient la valeur).
CharlesC
@ Charles.C c'est bizarre que je ne peux pas reproduire de mon côté.
Nicolas Filotto
Je suis à peu près sûr que la parallélisation du flux serait sous-optimale ici à moins que la chaîne d'entrée ne soit longue (~ 500 caractères). Au lieu de cela, si le tableau était grand, il serait probablement préférable de partitionner le tableau et d'exécuter chacun d'eux en parallèle.
lifesoordinary
2

Voici une solution:

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
la source
2

Depuis la version 3.4 Apache Common Lang 3 implémente la méthode containsAny .

Arthur Vaïsse
la source
Qui vérifie le tableau Char
Saikat
1

Une approche plus groovyesque serait d'utiliser inject en combinaison avec métaclasse :

J'adorerais dire:

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

Et la méthode serait:

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

Si vous avez besoin que containsAny soit présent pour toute future variable String, ajoutez la méthode à la classe au lieu de l'objet:

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

Essaye ça:

if (Arrays.asList(item1, item2, item3).stream().anyMatch(string::contains))
Óscar López
la source
15
La question est le contraire: la chaîne cible contient-elle l'une des chaînes de la liste.
Basil Bourque
1
La question est le contraire
Stéphane GRILLON
0

Et si vous recherchez une correspondance insensible à la casse, utilisez le modèle

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

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

}
vsingh
la source
0

Si vous seraching pour entiers mots que vous pouvez faire ce qui fonctionne le cas insensible .

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
la source
0

On peut aussi faire comme ça:

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
la source
-3

Ce qui suit devrait fonctionner pour vous en supposant que Strings est le tableau dans lequel vous recherchez:

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

où mykeytosearch est la chaîne dont vous souhaitez tester l'existence dans le tableau. mysearchComparator - est un comparateur qui serait utilisé pour comparer des chaînes.

Reportez-vous à Arrays.binarySearch pour plus d'informations.

Prahalad Deshpande
la source
2
Il convient de noter que binarySearch ne fonctionne que sur des tableaux triés, soit naturellement, soit par le comparateur donné (si tel est le cas).
Natix
-4
if (Arrays.asList(array).contains(string))
Salle Garrett
la source
10
La question est le contraire: la chaîne cible contient-elle l'une des chaînes de la liste.
Basil Bourque
2
La question est le contraire
Stéphane GRILLON