การเปรียบเทียบอักขระ space ในหลายรูปแบบ

ตัวอักขระพื้นที่ว่างหรือ space นั้นความจริงมีหลายรูปแบบ เช่น Non-breaking space, Em space, Thin space, และอื่นๆ ฯลฯ. เราอาจจะเรียกว่าเป็นอักขระพื้นที่ว่างแบบ unicode ก็ได้ แต่เพราะความที่เป็นอักขระที่แตกต่างกันกับการเคาะ space บนคีย์บอร์ดเฉยๆ ดังนั้นมันจึงมีปัญหาในการเปรียบเทียบด้วยเครื่องหมาย == หรือ === ดังจะสามารถทดลองได้จากโค้ดต่อไปนี้.

$space = ' ';
$spaces = [
    "\u{0020}",// normal space
    "\u{00A0}",// no-break space
    "\u{2003}",// em space
    "\u{2009}",// thin space
    "\u{2002}",// en space
    "\u{200A}",// hair space
];


foreach ($spaces as $eachSpace) {
    var_dump($eachSpace);
    var_dump($space === $eachSpace);
    if ($space !== $eachSpace) {
        echo '<span style="color: red;">No matched.</span><br>';
    } else {
        echo '<span style="color: green;">Matched.</span><br>';
    }
    echo '<br>';
}

จะพบว่าผลลัพธ์ของมันจะตรง (Matched) แค่รายการเดียว นอกนั้นจะไม่ตรง (No matched) ทั้งหมด เพราะตัวอักขระนั้นต่างกัน แม้ตาเราจะมองเห็นเป็นพื้นที่ว่างเหมือนกันก็ตาม.

แม้แต่การนับจำนวนอักขระก็จะต่างกัน ดังโค้ดต่อไปนี้.

// $spaces โปรดนำมาใช้จากโค้ดด้านบน
foreach ($spaces as $eachSpace) {
    var_dump($eachSpace);
    echo 'strlen: ' . strlen($eachSpace) . '<br>';
    echo 'mb_strlen: ' . mb_strlen($eachSpace) . '<br>';
    echo '<br>';
}

จะพบว่า strlen() จะนับได้ 1, 2, และที่เหลือเป็น 3 ทั้งหมด ในขณะที่ mb_strlen() จะนับได้ตรงกันทั้งหมดคือ 1.

การแก้ปัญหา

ให้ทำการแปลงอักขระด้วยวิธี normalize โดยใช้โค้ด \Normalizer::normalize($string, Normalizer::FORM_KD);.

// $spaces โปรดนำมาใช้จากโค้ดด้านบน
foreach ($spaces as $eachSpace) {
    var_dump($eachSpace);
    $normalized = \Normalizer::normalize($eachSpace, Normalizer::FORM_KD);
    var_dump($space === $normalized);
    if ($space !== $normalized) {
        echo '<span style="color: red;">No matched.</span><br>';
    } else {
        echo '<span style="color: green;">Matched.</span><br>';
    }
    echo '<br>';
}

ผลลัพธ์จากโค้ดด้านบนนี้จะเป็น Matched ทั้งหมด เพราะหลังจากที่ทำการ normalize เสร็จแล้ว อักขระพื้นที่ว่างที่เป็นรูปแบบต่างๆ ก็จะตรงกับตัวอักขระพื้นที่ว่าง (space) ที่เกิดจากการเคาะ space bar บนคีย์บอร์ดของเรา. ส่วนวิธีการนับจำนวนอักขระนั้น ยังคงยืนยันให้ใช้ mb_strlen() ตามเดิมเพราะสามารถนับจำนวนตัวอักษระได้ถูกต้องกว่า ไม่ใช่นับจากจำนวนไบต์.

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *

คุณอาจใช้แท็กHTMLและแอททริบิวต์เหล่านี้: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>