Comment puis-je compter le nombre de correspondances pour une regex?


97

Disons que j'ai une chaîne qui contient ceci:

HelloxxxHelloxxxHello

Je compile un modèle pour rechercher «Bonjour»

Pattern pattern = Pattern.compile("Hello");
Matcher matcher = pattern.matcher("HelloxxxHelloxxxHello");

Il devrait trouver trois correspondances. Comment puis-je compter le nombre de correspondances?

J'ai essayé différentes boucles et utilisé le matcher.groupCount()mais cela n'a pas fonctionné.


Y a-t-il une chance que votre chaîne de recherche ait des occurrences qui se chevauchent dans la chaîne d'entrée?
aioobe

Réponses:


177

matcher.find()ne trouve pas toutes les correspondances, seulement la correspondance suivante .

Solution pour Java 9+

long matches = matcher.results().count();

Solution pour Java 8 et versions antérieures

Vous devrez faire ce qui suit. ( À partir de Java 9, il existe une meilleure solution )

int count = 0;
while (matcher.find())
    count++;

Btw, matcher.groupCount()c'est quelque chose de complètement différent.

Exemple complet :

import java.util.regex.*;

class Test {
    public static void main(String[] args) {
        String hello = "HelloxxxHelloxxxHello";
        Pattern pattern = Pattern.compile("Hello");
        Matcher matcher = pattern.matcher(hello);

        int count = 0;
        while (matcher.find())
            count++;

        System.out.println(count);    // prints 3
    }
}

Gestion des correspondances qui se chevauchent

Lors du comptage des matches de aadans aaaal'extrait ci - dessus vous donnera 2 .

aaaa
aa
  aa

Pour obtenir 3 correspondances, c'est-à-dire ce comportement:

aaaa
aa
 aa
  aa

Vous devez rechercher une correspondance à l'index <start of last match> + 1comme suit:

String hello = "aaaa";
Pattern pattern = Pattern.compile("aa");
Matcher matcher = pattern.matcher(hello);

int count = 0;
int i = 0;
while (matcher.find(i)) {
    count++;
    i = matcher.start() + 1;
}

System.out.println(count);    // prints 3

Comptage du nombre de correspondances qui se produisent dans la chaîne. La méthode java.util.regex.Matcher.region (int start, int end) définit les limites de la région de ce matcher. La région est la partie de la séquence d'entrée qui sera recherchée pour trouver une correspondance. L'appel de cette méthode réinitialise le matcher, puis définit la région pour qu'elle commence à l'index spécifié par le paramètre start et se termine à l'index spécifié par le paramètre end. Essaye ça. while(matcher.find()){ matcher.region(matcher.end()-1, str.length()); count++; }
Mukesh Kumar Gupta

17

Cela devrait fonctionner pour les correspondances qui pourraient se chevaucher:

public static void main(String[] args) {
    String input = "aaaaaaaa";
    String regex = "aa";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(input);
    int from = 0;
    int count = 0;
    while(matcher.find(from)) {
        count++;
        from = matcher.start() + 1;
    }
    System.out.println(count);
}


3

Si vous souhaitez utiliser les flux Java 8 et êtes allergique aux whileboucles, vous pouvez essayer ceci:

public static int countPattern(String references, Pattern referencePattern) {
    Matcher matcher = referencePattern.matcher(references);
    return Stream.iterate(0, i -> i + 1)
            .filter(i -> !matcher.find())
            .findFirst()
            .get();
}

Avertissement: cela ne fonctionne que pour les matchs disjoints.

Exemple:

public static void main(String[] args) throws ParseException {
    Pattern referencePattern = Pattern.compile("PASSENGER:\\d+");
    System.out.println(countPattern("[ \"PASSENGER:1\", \"PASSENGER:2\", \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
    System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
    System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\", \"PASSENGER:1\" ]", referencePattern));
    System.out.println(countPattern("[  ]", referencePattern));
}

Cela imprime:

2
0
1
0

Voici une solution pour les correspondances disjointes avec les flux:

public static int countPattern(String references, Pattern referencePattern) {
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
            new Iterator<Integer>() {
                Matcher matcher = referencePattern.matcher(references);
                int from = 0;

                @Override
                public boolean hasNext() {
                    return matcher.find(from);
                }

                @Override
                public Integer next() {
                    from = matcher.start() + 1;
                    return 1;
                }
            },
            Spliterator.IMMUTABLE), false).reduce(0, (a, c) -> a + c);
}

1

Utilisez le code ci-dessous pour trouver le nombre de correspondances que l'expression régulière trouve dans votre entrée

        Pattern p = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL);// "regex" here indicates your predefined regex.
        Matcher m = p.matcher(pattern); // "pattern" indicates your string to match the pattern against with
        boolean b = m.matches();
        if(b)
        count++;
        while (m.find())
        count++;

Il s'agit d'un code généralisé et non spécifique, adaptez-le à vos besoins

N'hésitez pas à me corriger s'il y a une erreur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.