Java: Hitung Jumlah Kejadian Kata dalam String

Node Sumber: 1719850

Pengantar

Menghitung jumlah kemunculan kata dalam string adalah tugas yang cukup mudah, tetapi memiliki beberapa pendekatan untuk melakukannya. Anda harus memperhitungkan efisiensi metode juga, karena Anda biasanya ingin menggunakan alat otomatis ketika Anda tidak ingin melakukan pekerjaan manual – yaitu ketika ruang pencarian besar.

Dalam panduan ini, Anda akan mempelajari cara menghitung jumlah kemunculan kata dalam string di Java:

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

Kami akan mencari jumlah kemunculan targetWord, Menggunakan String.split(), Collections.frequency() dan Ekspresi Reguler.

Hitung Kemunculan Kata dalam String dengan String.split()

Cara paling sederhana untuk menghitung kemunculan kata target dalam sebuah string adalah dengan membagi string pada setiap kata, dan mengulanginya melalui array, menambah a wordCount pada setiap pertandingan. Perhatikan bahwa ketika sebuah kata memiliki tanda baca di sekitarnya, seperti wants. di akhir kalimat – pemisahan tingkat kata sederhana akan diperlakukan dengan benar wants dan wants. sebagai kata terpisah!

Untuk mengatasinya, Anda dapat dengan mudah menghapus semua tanda baca dari kalimat sebelum membelahnya:

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

Dalam majalah for loop, kami hanya mengulangi melalui array, memeriksa apakah elemen pada setiap indeks sama dengan targetWord. Jika ya, kita tingkatkan wordCount, yang pada akhir eksekusi, mencetak:

2

Hitung Kemunculan Kata dalam String dengan Koleksi.frekuensi()

Grafik Collections.frequency() metode menyediakan implementasi tingkat yang lebih bersih dan lebih tinggi, yang mengabstraksikan yang sederhana for loop, dan memeriksa kedua identitas (apakah suatu objek is objek lain) dan kesetaraan (apakah suatu objek sama dengan objek lain, tergantung pada fitur kualitatif objek itu).

Grafik frequency() metode menerima daftar untuk mencari, dan objek target, dan bekerja untuk semua objek lain juga, di mana perilaku tergantung pada bagaimana objek itu sendiri mengimplementasikan equals(). Dalam kasus string, equals() memeriksa isi string:


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

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

Di sini, kami telah mengonversi array yang diperoleh dari split() menjadi jawa ArrayList, menggunakan pembantu asList() metode dari Arrays kelas. Operasi pengurangan frequency() mengembalikan bilangan bulat yang menunjukkan frekuensi targetWord dalam daftar, dan menghasilkan:

2

Kemunculan Kata dalam String dengan Matcher (Ekspresi Reguler – RegEx)

Terakhir, Anda dapat menggunakan Ekspresi Reguler untuk mencari pola, dan menghitung jumlah pola yang cocok. Ekspresi Reguler dibuat untuk ini, jadi ini sangat cocok untuk tugas itu. Di Jawa, Pattern class digunakan untuk mewakili dan mengkompilasi Ekspresi Reguler, dan Matcher class digunakan untuk menemukan dan mencocokkan pola.

Menggunakan RegEx, kita dapat mengkodekan invariansi tanda baca ke dalam ekspresi itu sendiri, jadi tidak perlu memformat string secara eksternal atau menghapus tanda baca, yang lebih disukai untuk teks besar di mana menyimpan versi lain yang diubah dalam memori mungkin mahal:

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

Ini juga menghasilkan:

2

Tolok Ukur Efisiensi

Jadi, mana yang paling efisien? Mari kita jalankan benchmark kecil:

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

Setiap metode akan dijalankan 100000 kali (semakin tinggi angkanya, semakin rendah varians dan hasil karena kebetulan, karena hukum angka besar). Menjalankan kode ini menghasilkan:

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

Namun – apa yang terjadi jika kita membuat pencarian lebih mahal secara komputasi dengan membuatnya lebih besar? Mari kita buat kalimat sintetik:

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

Ini membuat string dengan konten:

hello world hello world hello world hello ...

Lihat panduan praktis dan praktis kami untuk mempelajari Git, dengan praktik terbaik, standar yang diterima industri, dan termasuk lembar contekan. Hentikan perintah Googling Git dan sebenarnya belajar itu!

Sekarang, jika kita mencari baik "halo" atau "dunia" – akan ada lebih banyak kecocokan daripada dua dari sebelumnya. Bagaimana metode kami lakukan sekarang di benchmark?

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

Sekarang, pemisahan array keluar paling cepat! Secara umum, tolok ukur bergantung pada berbagai faktor – seperti ruang pencarian, kata target, dll. dan kasus penggunaan pribadi Anda mungkin berbeda dari tolok ukur.

Saran: Cobalah metode pada teks Anda sendiri, catat waktunya, dan pilih yang paling efisien dan elegan untuk Anda.

Kesimpulan

Dalam panduan singkat ini, kita telah melihat bagaimana menghitung kemunculan kata untuk kata target, dalam sebuah string di Java. Kami telah memulai dengan memisahkan string dan menggunakan penghitung sederhana, diikuti dengan menggunakan Collections kelas pembantu, dan akhirnya, menggunakan Ekspresi Reguler.

Pada akhirnya, kami telah membandingkan metode, dan mencatat bahwa kinerjanya tidak linier, dan tergantung pada ruang pencarian. Untuk teks input yang lebih panjang dengan banyak kecocokan, array pemisahan tampaknya menjadi yang paling berkinerja. Cobalah ketiga metode tersebut sendiri, dan pilih yang paling efektif.

Stempel Waktu:

Lebih dari penyalahgunaan