Bagaimana cara menghitung jumlah kecocokan untuk ekspresi reguler?

97

Katakanlah saya memiliki string yang berisi ini:

HelloxxxHelloxxxHello

Saya menyusun pola untuk mencari 'Halo'

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

Ini harus menemukan tiga kecocokan. Bagaimana saya bisa menghitung berapa banyak pertandingan yang ada?

Saya sudah mencoba berbagai loop dan menggunakan matcher.groupCount()tetapi tidak berhasil.

Tony
sumber
Adakah kemungkinan string pencarian Anda memiliki kejadian yang tumpang tindih dalam string input?
aioobe

Jawaban:

177

matcher.find()tidak menemukan semua kecocokan, hanya kecocokan berikutnya .

Solusi untuk Java 9+

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

Solusi untuk Java 8 dan yang lebih lama

Anda harus melakukan hal berikut. ( Mulai dari Java 9, ada solusi yang lebih bagus )

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

Btw, matcher.groupCount() adalah sesuatu yang sangat berbeda.

Contoh lengkapnya :

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

Menangani pertandingan yang tumpang tindih

Saat menghitung kecocokan aadalam aaaacuplikan di atas akan memberi Anda 2 .

aaaa
aa
  aa

Untuk mendapatkan 3 pertandingan, yaitu perilaku ini:

aaaa
aa
 aa
  aa

Anda harus mencari kecocokan di indeks <start of last match> + 1sebagai berikut:

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
aioobe
sumber
Menghitung jumlah kecocokan yang terjadi dalam string. Metode java.util.regex.Matcher.region (int start, int end) menetapkan batas region matcher ini. Wilayah adalah bagian dari urutan masukan yang akan dicari untuk menemukan kecocokan. Memanggil metode ini akan menyetel ulang matcher, lalu menyetel kawasan untuk dimulai pada indeks yang ditentukan oleh parameter awal dan diakhiri pada indeks yang ditentukan oleh parameter akhir. Coba ini. while(matcher.find()){ matcher.region(matcher.end()-1, str.length()); count++; }
Mukesh Kumar Gupta
17

Ini harus bekerja untuk pertandingan yang mungkin tumpang tindih:

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);
}
Mary-Anne Wolf
sumber
5

Dari Java 9, Anda dapat menggunakan aliran yang disediakan oleh Matcher.results()

long matches = matcher.results().count();
vương trọng hồ
sumber
3

Jika Anda ingin menggunakan aliran Java 8 dan alergi terhadap whileloop, Anda dapat mencoba ini:

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

Penafian: ini hanya berfungsi untuk pertandingan terputus-putus.

Contoh:

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

Ini mencetak:

2
0
1
0

Ini adalah solusi untuk kecocokan terputus-putus dengan aliran:

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);
}
gil.fernandes
sumber
1

Gunakan kode di bawah ini untuk menemukan jumlah kecocokan yang ditemukan regex dalam masukan Anda

        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++;

Ini adalah kode umum, bukan kode spesifik, sesuaikan dengan kebutuhan Anda

Jangan ragu untuk mengoreksi saya jika ada kesalahan.

sayed amir
sumber