Dapatkan kata-kata yang paling sering digunakan dengan karakter khusus

Saya ingin mendapatkan kata yang paling sering digunakan dari sebuah array. Satu-satunya masalah adalah karakter Swedia (Å, Ä, dan Ö) hanya akan ditampilkan sebagai �.

$string = 'This is just a test post with the Swedish characters Å, Ä, and Ö. Also as lower cased characters: å, ä, and ö.';
echo '<pre>';
print_r(array_count_values(str_word_count($string, 1, 'àáãâçêéíîóõôúÀÁÃÂÇÊÉÍÎÓÕÔÚ')));
echo '</pre>';

Kode itu akan menampilkan yang berikut:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [�] => 1
    [�] => 1
    [and] => 2
    [�] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [�] => 1
    [�] => 1
    [�] => 1
)

Bagaimana saya bisa "melihat" karakter Swedia dan karakter khusus lainnya?


person Airikr    schedule 24.09.2016    source sumber
comment
Anda tidak perlu terkejut dengan fungsi PHP apa pun dengan nama yang dimulai dengan str tidak aman untuk multi-byte. Komentar pengguna di manual menyarankan alternatif.   -  person CBroe    schedule 24.09.2016
comment
@CBroe ...PHP function with a name starting with str... di mana fungsi ini?   -  person SaidbakR    schedule 24.09.2016
comment
coba fungsi ini mb_str_word_count sebagai gantinya str_word_count: stackoverflow.com/a/17725577/6797531   -  person CatalinB    schedule 24.09.2016
comment
@CatalinB Terima kasih tetapi hasilnya akan seperti ini: Array([This is just a test post with the Swedish characters �, �, and Ö. Also as lower cased characters: �, �, and �.] => 1)   -  person Airikr    schedule 24.09.2016


Jawaban (3)


Berikut adalah solusi dengan regex menggunakan tanda baca Unicode untuk membagi "kata" kemudian hanya menghitung kemunculan array biasa.

array_count_values(preg_split('/[[:punct:]\s]+/u', $string, -1, PREG_SPLIT_NO_EMPTY));

Menghasilkan:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

Ini telah diuji di konsol unicode, Anda mungkin ingin menerapkan pengkodean jika Anda menggunakan browser. Buatlah tag <meta> atau setel pengkodean dalam browser Anda, atau kirimkan header PHP.

person MarZab    schedule 24.09.2016

Semua ini berjalan dengan asumsi Anda menggunakan UTF-8.

Anda dapat mengambil pendekatan naif menggunakan preg_split() untuk membagi string Anda pada pemisah mana pun , tanda baca, atau karakter kontrol.

preg_split contoh:

$split = preg_split('/[\pZ\pP\pC]/u', $string, -1, PREG_SPLIT_NO_EMPTY);
print_r(array_count_values($split));

Keluaran:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

Ini berfungsi dengan baik untuk string yang Anda berikan, tetapi tidak serta merta memisahkan kata-kata dengan cara yang peka terhadap lokal. Misalnya kontraksi seperti "bukan" akan dipecah menjadi "bukan" dan "t" dengan ini.


Untungnya ekstensi Internasional menambahkan banyak fungsi untuk menangani hal-hal seperti ini di PHP7.

Rencananya adalah:

(*Perhatikan bahwa Anda mungkin ingin melakukan normalisasi terlepas dari metode apa yang Anda gunakan untuk memecah string - sebaiknya dilakukan sebelum preg_split di atas atau apa pun yang Anda pilih.)

Contoh internasional:

$string = Normalizer::normalize($string);

$iter = IntlBreakIterator::createWordInstance("sv_SE");
$iter->setText($string);
$words = $iter->getPartsIterator();

$split = [];
foreach ($words as $word) {
    // skip text fragments consisting only of a space or punctuation character
    if (IntlChar::isspace($word) || IntlChar::ispunct($word)) {
        continue;
    }
    $split[] = $word;
}

print_r(array_count_values($split));

Keluaran:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

Ini lebih bertele-tele tetapi mungkin bermanfaat jika Anda lebih memilih ICU (perpustakaan yang mendukung ekstensi Intl) untuk melakukan pekerjaan berat dalam memahami apa yang membentuk sebuah kata.

person user3942918    schedule 24.09.2016
comment
Terima kasih banyak atas jawaban yang sangat rinci. Jawaban Anda dan jawaban MarZab sangat bagus. Regex Anda akan menerima smiley sedangkan regex MarZab tidak. Jika saya bisa, saya akan menerima kedua jawaban tersebut tetapi karena regex MarZab tidak menerima smiley, saya akan menerima jawabannya. - person Airikr; 24.09.2016

Saya berhasil menghilangkan tanda � dengan menambahkan ÅåÄäÖö ke àáãâçêéíîóõôúÀÁÃÂÇÊÉÍÎÓÕÔÚ.

person Airikr    schedule 24.09.2016