web-dev-qa-db-ja.com

java正規表現一致カウント

ファイルがあり、ファイルにこれが含まれているとします。

HelloxxxHelloxxxHello

「Hello」を探すためにパターンをコンパイルします

Pattern pattern = Pattern.compile("Hello");

次に、入力ストリームを使用してファイルを読み取り、文字列に変換して、再実行できるようにします。

マッチャーがファイル内で一致を見つけると、それを示しますが、見つかった一致の数はわかりません。単純に、ストリング内で一致が見つかったということです。

そのため、文字列は比較的短く、使用しているバッファは200バイトなので、3つの一致が見つかるはずです。ただし、単に一致と表示されるだけで、一致の数は表示されません。

文字列内で発生した一致の数をカウントする最も簡単な方法は何ですか。さまざまなforループを試し、matcher.groupCount()を使用しましたが、どこでも高速になりません。

84
Tony

matcher.find()allの一致を検出せず、nextのみを検索します一致。

次のことを行う必要があります。

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

ところで、matcher.groupCount()はまったく違うものです。

完全な例

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

重複する一致の処理

aaaaaaの一致をカウントする場合、上記のスニペットは2を提供します。

aaaa
aa
  aa

3つの一致、つまりこの動作を取得するには:

aaaa
aa
 aa
  aa

次のように、インデックス<start of last match> + 1で一致を検索する必要があります。

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
157
aioobe

これは、重複する可能性のある一致に対して機能するはずです。

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

Java 8ストリームを使用し、whileループにアレルギーがある場合は、これを試すことができます。

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

免責事項:これは、ばらばらの一致に対してのみ機能します。

例:

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

これは印刷されます:

2
0
1
0

これは、ストリームとの互いに素な一致の解決策です。

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

これは役立つかもしれません:

public static void main(String[] args) {
    String hello = "HelloxxxHelloxxxHello";
    String []matches = hello.split("Hello");
    System.out.println(matches.length);    // prints 3
}
0
majid zareei