文字列内の単語を数える

1. 概要

このチュートリアルでは、Javaを使用して*特定の文字列内の単語をカウントするさまざまな方法*について説明します。

2. _StringTokenizer_の使用

  • Javaの文字列内の単語をカウントする簡単な方法は、_StringTokenizer_クラスを使用することです。

assertEquals(3, new StringTokenizer("three blind mice").countTokens());
assertEquals(4, new StringTokenizer("see\thow\tthey\trun").countTokens());
_StringTokenizer_は、タブやキャリッジリターンのように、自動的に*空白を処理します*。
しかし、ハイフンのように、場所によっては間違うかもしれません。
assertEquals(7, new StringTokenizer("the farmer's wife--she was from Albuquerque").countTokens());
この場合、「wife」と「she」を別の単語にしたいと思いますが、それらの間に空白がないため、デフォルトでは失敗します。
幸いなことに、__StringTokenizer __shipsは別のコンストラクターを使用します。 *デリミタをコンストラクタに渡して上記の動作をさせることができます:
assertEquals(7, new StringTokenizer("the farmer's wife--she was from Albuquerque", " -").countTokens());
これは、* CSVファイルのようなものから文字列内の単語をカウントしようとするときに便利です:*
assertEquals(10, new StringTokenizer("did,you,ever,see,such,a,sight,in,your,life", ",").countTokens());
そのため、_StringTokenizer_はシンプルであり、ほとんどの方法で取得できます。
余分な馬力の正規表現が私たちに与えることができるものを見てみましょう。

3. 正規表現

このタスクに意味のある正規表現を考え出すには、単語と見なすものを定義する必要があります。*単語は文字で始まり、スペース文字または句読点で終わる*。
これを念頭に置いて、文字列を指定して、スペースと句読点に遭遇するすべてのポイントでその文字列を分割し、結果の単語をカウントします。
assertEquals(7, countWordsUsingRegex("the farmer's wife--she was from Albuquerque"));
正規表現の力を確認するために、少し上げてみましょう。
assertEquals(9, countWordsUsingRegex("no&one#should%ever-write-like,this;but:well"));
区切り文字を_StringTokenizer_に渡すだけでこの問題を解決することは実用的ではありません。考えられるすべての句読点をリストしようとするために、本当に長い区切り文字を定義する必要があるからです。
*正規表現を渡す* _ [\ pP \ s
public static int countWordsUsingRegex(String arg) {
    if (arg == null) {
        return 0;
    }
    final String[] words = arg.split("[\pP\s&&[^']]+");
    return words.length;
}
*正規表現* _ [\ pP \ s
正規表現の詳細については、https://www.baeldung.com/regular-expressions-java [Baeldungの正規表現]を参照してください。

4. ループとString API

*他の方法は、出会った単語を追跡するフラグを持つことです。*
新しい単語に遭遇したときにフラグを_WORD_に設定し、単語数を増やしてから、単語以外(句読点またはスペース文字)に遭遇したときに_SEPARATOR_に戻ります。
このアプローチにより、正規表現で得たのと同じ結果が得られます。
assertEquals(9, countWordsManually("no&one#should%ever-write-like,this but   well"));
*句読点が実際には単語の区切り文字ではない特別な場合には注意する必要があります*、たとえば:
assertEquals(6, countWordsManually("the farmer's wife--she was from Albuquerque"));
ここで必要なのは、「農夫」を1つの単語として数えることです。ただし、アポストロフィ「」は句読点です。
正規表現バージョンでは、正規表現を使用して文字として適格でないものを定義する柔軟性がありました。 しかし、独自の実装を作成しているので、*この除外を別のメソッドで定義する必要があります*:
private static boolean isAllowedInWord(char charAt) {
    return charAt == '\'' || Character.isLetter(charAt);
}
したがって、ここで行ったことは、すべての文字と法的な句読点(この場合はアポストロフィ)を一言で許可することです。
実装でこのメソッドを使用できます。
public static int countWordsManually(String arg) {
    if (arg == null) {
        return 0;
    }
    int flag = SEPARATOR;
    int count = 0;
    int stringLength = arg.length();
    int characterCounter = 0;

    while (characterCounter < stringLength) {
        if (isAllowedInWord(arg.charAt(characterCounter)) && flag == SEPARATOR) {
            flag = WORD;
            count++;
        } else if (!isAllowedInWord(arg.charAt(characterCounter))) {
            flag = SEPARATOR;
        }
        characterCounter++;
    }
    return count;
}
最初の条件は、単語に遭遇するとマークを付け、カウンターをインクリメントします。 2番目の条件は、文字が文字でないかどうかを確認し、フラグを_SEPARATOR_に設定します。

5. 結論

このチュートリアルでは、いくつかのアプローチを使用して単語を数える方法を検討しました。 特定のユースケースに応じて、いずれかを選択できます。
いつものように、このチュートリアルのソースコードはhttps://github.com/eugenp/tutorials/tree/master/java-strings-3[GitHub上]にあります。