Java: Štetje števila pojavov besed v nizu

Predstavitev

Štetje števila pojavitev besed v nizu je precej lahka naloga, vendar ima za to več pristopov. Upoštevati morate tudi učinkovitost metode, saj boste običajno želeli uporabiti avtomatizirana orodja, ko ne želite opravljati ročnega dela – tj. ko je iskalni prostor velik.

V tem priročniku se boste naučili, kako prešteti število pojavitev besed v nizu v Javi:

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

Poiskali bomo število pojavitev targetWord, Uporaba String.split(), Collections.frequency() in regularni izrazi.

Preštej pojavitve besed v nizu z String.split()

Najenostavnejši način za štetje pojavljanja ciljne besede v nizu je razdelitev niza na vsako besedo in ponavljanje po matriki, s povečanjem wordCount na vsaki tekmi. Upoštevajte, da če ima beseda kakršno koli ločilo, kot je npr wants. na koncu stavka – preprosta razdelitev na ravni besed bo pravilno obravnavala wants in wants. kot ločene besede!

Temu se izognete tako, da preprosto odstranite vsa ločila iz stavka pred razdelitev:

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

v for zanke preprosto ponavljamo skozi matriko in preverjamo, ali je element pri vsakem indeksu enak targetWord. Če je, povečamo wordCount, ki na koncu izvajanja izpiše:

2

Preštej pojavitve besed v nizu z Collections.frequency()

O Collections.frequency() metoda zagotavlja veliko čistejšo izvedbo na višji ravni, ki abstrahira preprosto for zanke in preveri istovetnost obeh (ali je predmet is drug predmet) in enakost (ali je predmet enak drugemu predmetu, odvisno od kvalitativnih lastnosti tega predmeta).

O frequency() metoda sprejme seznam za iskanje in ciljni objekt ter deluje tudi za vse druge objekte, kjer je vedenje odvisno od tega, kako objekt sam izvaja equals(). V primeru nizov, equals() preverja za vsebino niza:


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

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

Tukaj smo pretvorili matriko, pridobljeno iz split() v Javo ArrayList, z uporabo pomočnika asList() metoda Arrays razred. Operacija zmanjšanja frequency() vrne celo število, ki označuje frekvenco targetWord na seznamu in rezultat:

2

Pojavitve besed v nizu z Ujemanje (regularni izrazi – RegEx)

Končno lahko uporabite regularne izraze za iskanje vzorcev in štetje ujemajočih se vzorcev. Za to so ustvarjeni regularni izrazi, zato je zelo naraven za to nalogo. V Javi je Pattern razred se uporablja za predstavljanje in prevajanje regularnih izrazov, in Matcher razred se uporablja za iskanje in ujemanje vzorcev.

Z uporabo RegExa lahko kodiramo invariantnost ločil v sam izraz, tako da ni potrebe po zunanjem oblikovanju niza ali odstranjevanju ločil, kar je bolje pri velikih besedilih, kjer je shranjevanje druge spremenjene različice v pomnilnik lahko drago:

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

Rezultat tega je tudi:

2

Merilo učinkovitosti

Torej, kateri je najučinkovitejši? Izvedimo majhno merilo uspešnosti:

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

Vsaka metoda bo izvedena 100000-krat (višje kot je število, manjša je varianca in rezultati zaradi naključja, zaradi zakona velikih števil). Zagon te kode povzroči:

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

Vendar – kaj se zgodi, če iskanje računalniško podražimo tako, da ga povečamo? Ustvarimo sintetični stavek:

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

To ustvari niz z vsebino:

hello world hello world hello world hello ...

Oglejte si naš praktični, praktični vodnik za učenje Gita z najboljšimi praksami, standardi, sprejetimi v panogi, in priloženo goljufijo. Nehajte Googlati ukaze Git in pravzaprav naučiti it!

Zdaj, če bi iskali "hello" ali "world" - bi bilo veliko več ujemanj kot ti dve od prej. Kakšne so zdaj naše metode v merilu uspešnosti?

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

Zdaj je razdelitev niza najhitrejša! Na splošno so merila uspešnosti odvisna od različnih dejavnikov – kot so iskalni prostor, ciljna beseda itd., vaš osebni primer uporabe pa se lahko razlikuje od primerjalne vrednosti.

Nasvet: Preizkusite metode na svojem besedilu, zabeležite si čase in izberite najbolj učinkovito in elegantno zase.

zaključek

V tem kratkem vodniku smo si ogledali, kako prešteti pojavitve besed za ciljno besedo v nizu v Javi. Začeli smo z razdelitvijo niza in uporabo preprostega števca, čemur je sledila uporaba Collections pomožni razred in končno z uporabo regularnih izrazov.

Na koncu smo primerjali metode in opazili, da zmogljivost ni linearna in je odvisna od iskalnega prostora. Za daljša vnosna besedila z veliko ujemanji se zdi, da je razdelitev nizov najučinkovitejša. Sami preizkusite vse tri metode in izberite najučinkovitejšega.

Časovni žig:

Več od Stackabuse