Làm cách nào để đếm số trận đấu cho một regex?


97

Giả sử tôi có một chuỗi chứa cái này:

HelloxxxHelloxxxHello

Tôi biên dịch một mẫu để tìm kiếm 'Xin chào'

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

Nó sẽ tìm thấy ba trận đấu. Làm cách nào để đếm xem đã có bao nhiêu trận đấu?

Tôi đã thử các vòng lặp khác nhau và sử dụng matcher.groupCount()nhưng nó không hoạt động.


Bất kỳ khả năng nào chuỗi tìm kiếm của bạn có thể xuất hiện chồng chéo trong chuỗi đầu vào?
aioobe

Câu trả lời:


177

matcher.find()không tìm thấy tất cả các trận đấu, chỉ các trận đấu tiếp theo .

Giải pháp cho Java 9+

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

Giải pháp cho Java 8 trở lên

Bạn sẽ phải làm như sau. ( Bắt đầu từ Java 9, có một giải pháp tốt hơn )

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

Btw, matcher.groupCount()là một cái gì đó hoàn toàn khác.

Toàn bộ ví dụ :

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

Xử lý các kết quả trùng khớp

Khi đếm các trận đấu aatrong aaaađoạn mã trên sẽ cho bạn 2 .

aaaa
aa
  aa

Để có 3 trận đấu, tức là hành vi này:

aaaa
aa
 aa
  aa

Bạn phải tìm kiếm một kết quả phù hợp tại chỉ mục <start of last match> + 1như sau:

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

Đếm số trận đấu xảy ra trong chuỗi. Phương thức java.util.regex.Matcher.region (int start, int end) đặt giới hạn của vùng của trình so khớp này. Vùng là một phần của chuỗi đầu vào sẽ được tìm kiếm để tìm một kết quả phù hợp. Việc gọi phương thức này sẽ đặt lại trình so khớp, rồi đặt vùng bắt đầu ở chỉ mục được chỉ định bởi tham số bắt đầu và kết thúc ở chỉ mục được chỉ định bởi tham số kết thúc. Thử cái này. while(matcher.find()){ matcher.region(matcher.end()-1, str.length()); count++; }
Mukesh Kumar Gupta

17

Điều này sẽ hoạt động đối với các kết quả phù hợp có thể trùng lặp:

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

Nếu bạn muốn sử dụng các luồng Java 8 và bị dị ứng với whilecác vòng lặp, bạn có thể thử cách này:

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

Tuyên bố từ chối trách nhiệm: điều này chỉ hoạt động cho các trận đấu rời rạc.

Thí dụ:

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

Điều này in ra:

2
0
1
0

Đây là một giải pháp cho các trận đấu rời rạc với các luồng:

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

Sử dụng mã bên dưới để tìm số lượng kết quả phù hợp mà regex tìm thấy trong đầu vào của bạn

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

Tuy nhiên, đây là một mã tổng quát không cụ thể, hãy điều chỉnh nó cho phù hợp với nhu cầu của bạn

Xin vui lòng sửa chữa cho tôi nếu có bất kỳ sai lầm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.