Conteggio delle parole in una stringa con Java

1. Panoramica

In questo tutorial, esamineremo diversi modi di contare le parole in una determinata stringa utilizzando Java.

2. Utilizzo di StringTokenizer

Un modo semplice per contare le parole in una stringa in Java è usare la classe StringTokenizer :

assertEquals(3, new StringTokenizer("three blind mice").countTokens()); assertEquals(4, new StringTokenizer("see\thow\tthey\trun").countTokens());

Nota che StringTokenizer si prende automaticamente cura degli spazi bianchi , come le tabulazioni e i ritorni a capo.

Tuttavia, in alcuni punti potrebbe essere un errore, come i trattini:

assertEquals(7, new StringTokenizer("the farmer's wife--she was from Albuquerque").countTokens());

In questo caso, vorremmo che "moglie" e "lei" fossero parole diverse, ma poiché non ci sono spazi vuoti tra di loro, le impostazioni predefinite ci mancano.

Fortunatamente, StringTokenizer viene fornito con un altro costruttore. Possiamo passare un delimitatore nel costruttore per far funzionare quanto sopra:

assertEquals(7, new StringTokenizer("the farmer's wife--she was from Albuquerque", " -").countTokens());

Ciò è utile quando si tenta di contare le parole in una stringa da qualcosa come un file CSV:

assertEquals(10, new StringTokenizer("did,you,ever,see,such,a,sight,in,your,life", ",").countTokens());

Quindi, StringTokenizer è semplice e ci porta quasi sempre lì.

Vediamo però quale potenza extra possono darci le espressioni regolari.

3. Espressioni regolari

Per poter trovare un'espressione regolare significativa per questo compito, dobbiamo definire ciò che consideriamo una parola: una parola inizia con una lettera e termina con uno spazio o un segno di punteggiatura .

Con questo in mente, data una stringa, quello che vogliamo fare è dividere quella stringa in ogni punto in cui incontriamo spazi e segni di punteggiatura, quindi contare le parole risultanti.

assertEquals(7, countWordsUsingRegex("the farmer's wife--she was from Albuquerque"));

Alziamo un po 'le cose per vedere il potere di regex:

assertEquals(9, countWordsUsingRegex("no&one#should%ever-write-like,this;but:well"));

Non è pratico risolvere questo problema semplicemente passando un delimitatore a StringTokenizer poiché dovremmo definire un delimitatore molto lungo per cercare di elencare tutti i possibili segni di punteggiatura.

Si scopre che davvero non dobbiamo fare molto, passare la regex [\ pP \ s && [^ ']] + al metodo split della classe String farà il trucco :

public static int countWordsUsingRegex(String arg) { if (arg == null) { return 0; } final String[] words = arg.split("[\pP\s&&[^']]+"); return words.length; }

L'espressione regolare [\ pP \ s && [^ ']] + trova qualsiasi lunghezza dei segni di punteggiatura o degli spazi e ignora il segno di punteggiatura apostrofo.

Per saperne di più sulle espressioni regolari, fare riferimento a Espressioni regolari su Baeldung.

4. Loop e API String

L'altro metodo è avere un flag che tenga traccia delle parole che sono state incontrate.

Impostiamo il flag su WORD quando incontriamo una nuova parola e incrementiamo il conteggio delle parole, quindi torniamo su SEPARATOR quando incontriamo una non-parola (punteggiatura o spazi).

Questo approccio ci dà gli stessi risultati che abbiamo ottenuto con le espressioni regolari:

assertEquals(9, countWordsManually("no&one#should%ever-write-like,this but well")); 

Dobbiamo stare attenti ai casi speciali in cui i segni di punteggiatura non sono realmente separatori di parole , ad esempio:

assertEquals(6, countWordsManually("the farmer's wife--she was from Albuquerque"));

Quello che vogliamo qui è contare "contadino" come una parola, sebbene l'apostrofo "" "sia un segno di punteggiatura.

Nella versione regex, avevamo la flessibilità di definire ciò che non si qualifica come un personaggio usando la regex. Ma ora che stiamo scrivendo la nostra implementazione, dobbiamo definire questa esclusione in un metodo separato :

private static boolean isAllowedInWord(char charAt)  

Quindi quello che abbiamo fatto qui è di consentire in una parola tutti i caratteri e i segni di punteggiatura legali, l'apostrofo in questo caso.

Ora possiamo utilizzare questo metodo nella nostra implementazione:

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

La prima condizione contrassegna una parola quando ne incontra una e incrementa il contatore. La seconda condizione controlla se il carattere non è una lettera e imposta il flag su SEPARATOR .

5. conclusione

In questo tutorial, abbiamo esaminato i modi per contare le parole utilizzando diversi approcci. Possiamo sceglierne uno a seconda del nostro particolare caso d'uso.

Come al solito, il codice sorgente di questo tutorial può essere trovato su GitHub.