รับคำที่ใช้บ่อยที่สุดพร้อมอักขระพิเศษ

ฉันต้องการรับคำที่ใช้มากที่สุดจากอาร์เรย์ ปัญหาเดียวคืออักขระภาษาสวีเดน (Å, Ä และ Ö) จะแสดงเป็น � เท่านั้น

$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>';

รหัสนั้นจะแสดงผลดังต่อไปนี้:

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
)

ฉันจะทำให้ "เห็น" ตัวอักษรภาษาสวีเดนและตัวอักษรพิเศษอื่นๆ ได้อย่างไร?


person Airikr    schedule 24.09.2016    source แหล่งที่มา
comment
คุณไม่ควรแปลกใจกับฟังก์ชัน PHP ใดๆ ที่มีชื่อขึ้นต้นด้วย str ซึ่งไม่ปลอดภัยสำหรับหลายไบต์ ความคิดเห็นของผู้ใช้ในคู่มือแนะนำทางเลือกอื่น   -  person CBroe    schedule 24.09.2016
comment
@CBroe ...PHP function with a name starting with str... ฟังก์ชันนี้อยู่ที่ไหน   -  person SaidbakR    schedule 24.09.2016
comment
ลองใช้ฟังก์ชันนี้ mb_str_word_count แทน str_word_count: stackoverflow.com/a/17725577/6797531   -  person CatalinB    schedule 24.09.2016
comment
@CatalinB ขอบคุณ แต่ผลลัพธ์จะเป็นเช่นนี้: 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


คำตอบ (3)


นี่คือวิธีแก้ปัญหาสำหรับ regex โดยใช้เครื่องหมายวรรคตอน Unicode เพื่อแยก "คำ" จากนั้นเพียงนับจำนวนอาร์เรย์ปกติ

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

ผลิต:

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
)

สิ่งนี้ได้รับการทดสอบในคอนโซล Unicode คุณอาจต้องการใช้การเข้ารหัสหากคุณใช้เบราว์เซอร์ สร้างแท็ก <meta> หรือตั้งค่าการเข้ารหัสภายในเบราว์เซอร์ของคุณ หรือส่งส่วนหัว PHP

person MarZab    schedule 24.09.2016

ทั้งหมดนี้ทำงานภายใต้สมมติฐานว่าคุณใช้ UTF-8

คุณสามารถใช้แนวทางไร้เดียงสาได้โดยใช้ preg_split() เพื่อแยกสตริงของคุณบนตัวคั่นใดๆ เครื่องหมายวรรคตอน หรืออักขระควบคุม

preg_split ตัวอย่าง:

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

เอาท์พุท:

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
)

วิธีนี้ใช้ได้ผลดีกับสตริงที่คุณระบุ แต่ไม่จำเป็นต้องแยกคำในลักษณะที่รับรู้ถึงสถานที่ ตัวอย่างเช่น การย่อคำเช่น "is't" จะแบ่งออกเป็น "isn" และ "t" ตามคำนี้


โชคดีที่ ส่วนขยาย Intl ได้เพิ่มฟังก์ชันการทำงานมากมายในการจัดการกับสิ่งต่างๆ ในลักษณะนี้ใน PHP7

แผนจะเป็น:

  • *ทำให้เป็นมาตรฐานอินพุตด้วย Normalizer::normalize() เพื่อให้แน่ใจว่ากราฟทั้งหมดได้รับการเข้ารหัสในลักษณะที่สอดคล้องกัน ตัวอย่างเช่น ä อาจถูกเข้ารหัส และด้วยเหตุนี้จึงนับได้หลายวิธี:

    • U+00E4 'LATIN SMALL LETTER A WITH DIAERESIS' or
    • U+0061 'LATIN SMALL LETTER A' ตามด้วย U+0308 'COMBINING DIAERISIS'
  • รับ IntlBreakIterator ที่แบ่งคำในลักษณะขึ้นอยู่กับสถานที่ผ่านทาง IntlBreakIterator::createWordInstance(). สิ่งนี้จะเข้าใจสิ่งที่ประกอบขึ้นเป็น "คำ" สำหรับสถานที่ที่กำหนด รวมถึงการจัดการคำย่อเช่น "ไม่ใช่"

  • รับ IntlPartsIterator ผ่านทาง IntlBreakIterator::getPartsIterator() เพื่อความสะดวกในการวนซ้ำส่วนของข้อความ

  • ข้ามสิ่งที่คุณไม่สนใจผ่าน IntlChar::ispunct() และ IntlChar::isspace()

(*โปรดทราบว่าคุณอาจต้องการดำเนินการทำให้เป็นมาตรฐานโดยไม่คำนึงถึงวิธีที่คุณใช้ในการแยกสตริง - ควรดำเนินการก่อน preg_split ด้านบนหรือวิธีใดก็ตามที่คุณตัดสินใจดำเนินการ)

ตัวอย่างระหว่างประเทศ:

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

เอาท์พุท:

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
)

นี่เป็นรายละเอียดมากกว่าแต่อาจคุ้มค่าหากคุณต้องการ ICU (ไลบรารีที่สนับสนุนส่วนขยาย Intl) เพื่อทำการยกของหนักเมื่อต้องทำความเข้าใจว่าอะไรเป็นส่วนประกอบของคำ

person user3942918    schedule 24.09.2016
comment
ขอบคุณมากสำหรับคำตอบที่ละเอียดมาก คำตอบของคุณทั้งสองและคำตอบของ MarZab นั้นดีมาก regex ของคุณจะยอมรับสไมลี่ ในขณะที่ regex ของ MarZab จะไม่ยอมรับ ถ้าทำได้ ฉันจะยอมรับทั้งสองคำตอบ แต่เนื่องจาก regex ของ MarZab ไม่ยอมรับสไมลี่ ฉันจะยอมรับคำตอบของเขาแทน - person Airikr; 24.09.2016

ฉันสามารถลบเครื่องหมาย � ได้โดยการเพิ่ม ÅåÄäÖö ลงใน àáãâçêéíîóõôúÀÁÃÂÇÊÉÍÎÓÕÔÚ

person Airikr    schedule 24.09.2016