Java: stringis esinevate sõnade arv

Sissejuhatus

Sõna esinemiste arvu loendamine stringis on üsna lihtne ülesanne, kuid sellel on mitu lähenemisviisi. Peate arvestama ka meetodi tõhususega, kuna tavaliselt soovite kasutada automatiseeritud tööriistu, kui te ei soovi käsitsi tööd teha – st kui otsinguruum on suur.

Sellest juhendist saate teada, kuidas loendada Java-s stringis esinevate sõnade arvu:

String searchText = "Your body may be chrome, but the heart never changes. It wants what it wants.";
String targetWord = "wants";

Otsime selle esinemiste arvu targetWord, Kasutamine String.split(), Collections.frequency() ja regulaaravaldised.

Loendage sõna esinemised stringis koos String.split()

Lihtsaim viis sihtsõna esinemise loendamiseks stringis on iga sõna string poolitada ja massiivi itereerida, suurendades wordCount igal matšil. Pange tähele, et kui sõna ümber on kirjavahemärgid, nt wants. lause lõpus – lihtne sõnatasandi poolitus käsitleb õigesti wants ja wants. eraldi sõnadena!

Selle lahendamiseks saate lausest hõlpsasti eemaldada kõik kirjavahemärgid enne selle jagamine:

String[] words = searchText.replaceAll("p{Punct}", "").split(" ");

int wordCount = 0;
for (int i=0; i < words.length; i++)
    if (words[i].equals(targetWord))
        wordCount++;
System.out.println(wordCount);

aasta for tsükkel, kordame lihtsalt massiivi läbi, kontrollides, kas iga indeksi element on võrdne targetWord. Kui on, suurendame wordCount, mis täitmise lõpus prindib:

2

Loendage sõna esinemised stringis koos Collections.frequency()

. Collections.frequency() meetod pakub palju puhtamat, kõrgemal tasemel teostust, mis võtab ära lihtsa for silmus ja kontrollib mõlema identiteeti (kas objekt is teine ​​objekt) ja võrdsus (kas objekt on võrdne teise objektiga, olenevalt selle objekti kvalitatiivsetest tunnustest).

. frequency() meetod aktsepteerib otsimiseks loendit ja sihtobjekti ning töötab ka kõigi teiste objektide puhul, kus käitumine sõltub sellest, kuidas objekt ise rakendab equals(). Stringide puhul equals() kontrollib stringi sisu:


searchText = searchText.replaceAll("p{Punct}", "");

int wordCount = Collections.frequency(Arrays.asList(searchText.split(" ")), targetWord);
System.out.println(wordCount);

Siin oleme teisendanud massiivi, mis on saadud split() Javasse ArrayList, kasutades abistajat asList() meetod Arrays klass. Vähendamise operatsioon frequency() tagastab täisarvu, mis tähistab sagedust targetWord loendis ja tulemuseks on:

2

Sõna esinemised stringis koos Vastaja (regulaaravaldised – regEx)

Lõpuks saate kasutada regulaaravaldisi mustrite otsimiseks ja sobitatud mustrite arvu loendamiseks. Selle jaoks on loodud regulaaravaldised, nii et see sobib ülesandega väga loomulikult. Javas on Pattern klassi kasutatakse regulaaravaldiste esitamiseks ja koostamiseks ning Matcher klassi kasutatakse mustrite leidmiseks ja sobitamiseks.

RegExi abil saame kirjavahemärkide invariantsi avaldisesse endasse kodeerida, nii et pole vaja stringi väliselt vormindada ega kirjavahemärke eemaldada, mis on eelistatav suurte tekstide puhul, kus mõne muu muudetud versiooni mällu salvestamine võib osutuda ohtlikuks:

Pattern pattern = Pattern.compile("b%s(?!w)".format(targetWord));

Pattern pattern = Pattern.compile("bwants(?!w)");
Matcher matcher = pattern.matcher(searchText);

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

System.out.println(wordCount);

Selle tulemuseks on ka:

2

Tõhususe võrdlusalus

Niisiis, milline on kõige tõhusam? Teeme väikese võrdlusaluse:

int runs = 100000;

long start1 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithSplit(searchText, targetWord);
}

long end1 = System.currentTimeMillis();
System.out.println(String.format("Array split approach took: %s miliseconds", end1-start1));

long start2 = System.currentTimeMillis();
  for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithCollections(searchText, targetWord);
}

long end2 = System.currentTimeMillis();
System.out.println(String.format("Collections.frequency() approach took: %s miliseconds", end2-start2));

long start3 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    int result = countOccurencesWithRegex(searchText, targetWord);
}

long end3 = System.currentTimeMillis();
System.out.println(String.format("Regex approach took: %s miliseconds", end3-start3));

Iga meetodit käivitatakse 100000 XNUMX korda (mida suurem arv, seda väiksem on juhuslikkuse tõttu, suurte arvude seadusest tulenevalt, on dispersioon ja tulemused). Selle koodi käivitamine annab tulemuseks:

Array split approach took: 152 miliseconds
Collections.frequency() approach took: 140 miliseconds
Regex approach took: 92 miliseconds

Samas – mis juhtub, kui muudame otsingu arvutuslikult kallimaks, muutes selle suuremaks? Loome sünteetilise lause:

List possibleWords = Arrays.asList("hello", "world ");
StringBuffer searchTextBuffer = new StringBuffer();

for (int i = 0; i < 100; i++) {
    searchTextBuffer.append(String.join(" ", possibleWords));
}
System.out.println(searchTextBuffer);

See loob stringi sisuga:

hello world hello world hello world hello ...

Tutvuge meie praktilise ja praktilise Giti õppimise juhendiga, mis sisaldab parimaid tavasid, tööstusharus aktsepteeritud standardeid ja kaasas olevat petulehte. Lõpetage Giti käskude guugeldamine ja tegelikult õppima seda!

Kui me nüüd otsiksime kas "tere" või "maailm", siis oleks palju rohkem vasteid kui kaks varasemat. Kuidas meie meetodid praegu võrdlusaluses toimivad?

Array split approach took: 606 miliseconds
Collections.frequency() approach took: 899 miliseconds
Regex approach took: 801 miliseconds

Nüüd tuleb massiivi jagamine kõige kiiremini välja! Üldiselt sõltuvad võrdlusalused erinevatest teguritest – näiteks otsinguruumist, sihtsõnast jne – ning teie isiklik kasutusjuht võib võrdlusalusest erineda.

Nõuanne: Proovige meetodeid oma tekstis, märkige üles ajad ja valige enda jaoks kõige tõhusam ja elegantsem.

Järeldus

Selles lühikeses juhendis oleme vaatlenud, kuidas loendada Java keele stringis sihtsõna esinemisi. Alustasime stringi tükeldamisest ja lihtsa loenduri kasutamisest, millele järgnes Collections abiklass ja lõpuks regulaaravaldiste kasutamine.

Lõpuks oleme meetodeid võrdlenud ja märkinud, et jõudlus ei ole lineaarne ja sõltub otsinguruumist. Pikemate ja paljude vastetega sisendtekstide puhul näib massiivide poolitamine olevat kõige tõhusam. Proovige kõiki kolme meetodit ise ja valige kõige tõhusam.

Ajatempel:

Veel alates Stackabus