2010-03-31 8 views
10

इस स्ट्रिंग को "主楼 怎么 走" को अलग-अलग वर्णों में विभाजित करने की कोशिश कर रहा है (मुझे कोई सरणी चाहिए) mb_split का उपयोग करके कोई भाग्य नहीं ... कोई सुझाव?PHP: अलग-अलग अक्षरों में मल्टीबाइट स्ट्रिंग (शब्द) को विभाजित करें

धन्यवाद!

+0

बाहर http://stackoverflow.com/questions/1032674/string-to-array-and-back-php – Smandoli

+5

चेक कृपया ध्यान देना है, यह एक multibyte स्ट्रिंग है। – Peterim

उत्तर

20

उदाहरण

$chars = preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY); 
+0

यह केवल यूटीएफ -8 एन्कोडिंग काम करेगा। –

+0

पेट्र के साथ सहमत हैं। मैंने बीआईजी 5 के साथ कोशिश की, यह काम नहीं करता है! –

9

यह करने के लिए एक बदसूरत तरीका है:

mb_internal_encoding("UTF-8"); // this IS A MUST!! PHP has trouble with multibyte 
           // when no internal encoding is set! 
$string = "....."; 
$chars = array(); 
for ($i = 0; $i < mb_strlen($string); $i++) { 
    $chars[] = mb_substr($string, $i, 1); // only one char to go to the array 
} 

तुम भी यह पहले internal_encoding स्थापित करने के साथ mb_split साथ अपने तरीके से प्रयास करना चाहिए।

+0

'mb_internal_encoding (" यूटीएफ -8 "); 'इससे ​​मुझे बहुत मदद मिली। – ivkremer

+0

मुझे यह जवाब पसंद है, क्योंकि मैंने समान रूप से लंबे हिस्सों में पाठ को विभाजित करने के लिए सरल utf-8 सुरक्षित तरीका खोजने के लिए कड़ी मेहनत की है। न केवल पात्रों को गाते हैं बल्कि भागों। पिछले mb_substr पैरामीटर के रूप में केवल $ i + 5 और 5 को संपादित करना था और मेरा टेक्स्ट 5 utf8 वर्ण तारों में विभाजित किया गया था। Thnx बहुत। –

+0

महान समाधान :) – clarkk

3

आप ग्रफीम कार्यों का उपयोग कर सकते हैं (पीएचपी 5.3 या intl 1.0) और IntlBreakIterator (पीएचपी 5.5 या intl 3.0) के लिए, 'यू' विकल्प के साथ एक नियमित अभिव्यक्ति का प्रयास करें। निम्नलिखित कोड intl और mbstring और पीसीआरई कार्यों के बीच अंतर दिखाता है।

// http://www.php.net/manual/function.grapheme-strlen.php 
$string = "a\xCC\x8A" // 'LATIN SMALL LETTER A WITH RING ABOVE' (U+00E5) 
     ."o\xCC\x88"; // 'LATIN SMALL LETTER O WITH DIAERESIS' (U+00F6) 

$expected = ["a\xCC\x8A", "o\xCC\x88"]; 
$expected2 = ["a", "\xCC\x8A", "o", "\xCC\x88"]; 

var_dump(
    $expected === str_to_array($string), 
    $expected === str_to_array2($string), 
    $expected2 === str_to_array3($string), 
    $expected2 === str_to_array4($string), 
    $expected2 === str_to_array5($string) 
); 

function str_to_array($string) 
{ 
    $length = grapheme_strlen($string); 
    $ret = []; 

    for ($i = 0; $i < $length; $i += 1) { 
     $ret[] = grapheme_substr($string, $i, 1); 
    } 

    return $ret; 
} 

function str_to_array2($string) 
{ 
    $it = IntlBreakIterator::createCharacterInstance('en_US'); 
    $it->setText($string); 

    $ret = []; 
    $prev = 0; 

    foreach ($it as $pos) { 

     $char = substr($string, $prev, $pos - $prev); 

     if ('' !== $char) { 
      $ret[] = $char; 
     } 

     $prev = $pos; 
    } 

    return $ret; 
} 

function str_to_array3($string) 
{ 
    $it = IntlBreakIterator::createCodePointInstance(); 
    $it->setText($string); 

    $ret = []; 
    $prev = 0; 

    foreach ($it as $pos) { 

     $char = substr($string, $prev, $pos - $prev); 

     if ('' !== $char) { 
      $ret[] = $char; 
     } 

     $prev = $pos; 
    } 

    return $ret; 
} 

function str_to_array4($string) 
{ 
    $length = mb_strlen($string, "UTF-8"); 
    $ret = []; 

    for ($i = 0; $i < $length; $i += 1) { 
     $ret[] = mb_substr($string, $i, 1, "UTF-8"); 
    } 

    return $ret; 
} 

function str_to_array5($string) { 
    return preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY); 
} 

जब उत्पादन वातावरण पर काम कर रहा है, तो आप लगभग सभी ग्रफीम के बाद से स्थानापन्न चरित्र के साथ अवैध बाइट क्रम को बदलने के लिए और mbstring कार्यों को संभाल नहीं कर सकते हैं अवैध बाइट क्रम की जरूरत है। यदि आपके पास रुचि है, तो मेरा पिछला उत्तर देखें: https://stackoverflow.com/a/13695364/531320

यदि आप परफॉर्मेंस नहीं लेते हैं, तो htmlspecialchars और htmlspecialchars_decode का उपयोग किया जा सकता है। इस तरह की योग्यता यूटीएफ -8 के अलावा विभिन्न एन्कोडिंग का समर्थन कर रही है।

function str_to_array6($string, $encoding = 'UTF-8') 
{ 
    $ret = []; 
    str_replace_callback($string, function($char, $index) use (&$ret) { $ret[] = $char; return ''; }, $encoding); 
    return $ret; 
} 

function str_replace_callback($string, $callable, $encoding = 'UTF-8') 
{ 
    $str_size = strlen($string); 
    $string = str_scrub($string, $encoding); 

    $ret = ''; 
    $char = ''; 
    $index = 0; 

    for ($pos = 0; $pos < $str_size; ++$pos) { 

     $char .= $string[$pos]; 

     if (str_check_encoding($char, $encoding)) { 

      $ret .= $callable($char, $index); 
      $char = ''; 
      ++$index; 
     } 

    } 

    return $ret; 
} 

function str_check_encoding($string, $encoding = 'UTF-8') 
{ 
    $string = (string) $string; 
    return $string === htmlspecialchars_decode(htmlspecialchars($string, ENT_QUOTES, $encoding)); 
} 

function str_scrub($string, $encoding = 'UTF-8') 
{ 
    return htmlspecialchars_decode(htmlspecialchars($string, ENT_SUBSTITUTE, $encoding)); 
} 

आपको UTF-8 के विनिर्देश जानने के लिए चाहते हैं, बाइट हेरफेर अभ्यास करने के लिए अच्छा तरीका है।

function str_to_array6($string) 
{ 
    // REPLACEMENT CHARACTER (U+FFFD) 
    $substitute = "\xEF\xBF\xBD"; 
    $size = strlen($string); 
    $ret = []; 

    for ($i = 0; $i < $size; $i += 1) { 

     if ($string[$i] <= "\x7F") { 

      $ret[] = $string[$i]; 

     } elseif ("\xC2" <= $string[$i] && $string[$i] <= "\xDF") { 

      if (!isset($string[$i+1])) { 

       $ret[] = $substitute; 
       return $ret; 

      } elseif ($string[$i+1] < "\x80" || "\xBF" < $string[$i+1]) { 

       $ret[] = $substitute; 

      } else { 

       $ret[] = substr($string, $i, 2); 
       $i += 1; 

      } 

     } elseif ("\xE0" <= $string[$i] && $string[$i] <= "\xEF") { 

      $left = "\xE0" === $string[$i] ? "\xA0" : "\x80"; 
      $right = "\xED" === $string[$i] ? "\x9F" : "\xBF"; 

      if (!isset($string[$i+1])) { 

       $ret[] = $substitute; 
       return $ret; 

      } elseif ($string[$i+1] < $left || $right < $string[$i+1]) { 

       $ret[] = $substitute; 

      } else { 

       if (!isset($string[$i+2])) { 

        $ret[] = $substitute; 
        return $ret; 

       } elseif ($string[$i+2] < "\x80" || "\xBF" < $string[$i+2]) { 

        $ret[] = $substitute; 
        $i += 1; 

       } else { 

        $ret[] = substr($string, $i, 3); 
        $i += 2; 

       } 

      } 

     } elseif ("\xF0" <= $string[$i] && $string[$i] <= "\xF4") { 

      $left = "\xF0" === $string[$i] ? "\x90" : "\x80"; 
      $right = "\xF4" === $string[$i] ? "\x8F" : "\xBF"; 

      if (!isset($string[$i+1])) { 

       $ret[] = $substitute; 
       return $ret; 

      } elseif ($string[$i+1] < $left || $right < $string[$i+1]) { 

       $ret[] = $substitute; 

      } else { 

       if (!isset($string[$i+2])) { 

        $ret[] = $substitute; 
        return $ret; 

       } elseif ($string[$i+2] < "\x80" || "\xBF" < $string[$i+2]) { 

        $ret[] = $substitute; 
        $i += 1; 

       } else { 

        if (!isset($string[$i+3])) { 

         $ret[] = $substitute; 
         return $ret; 

        } elseif ($string[$i+3] < "\x80" || "\xBF" < $string[$i+3]) { 

         $ret[] = $substitute; 
         $i += 2; 

        } else { 

         $ret[] = substr($string, $i, 4); 
         $i += 3; 

        } 

       } 

      } 

     } else { 

      $ret[] = $substitute; 

     } 

    } 

    return $ret; 

} 

इन कार्यों के बीच बेंचमार्क का परिणाम यहां है।

grapheme 
0.12967610359192 
IntlBreakIterator::createCharacterInstance 
0.17032408714294 
IntlBreakIterator::createCodePointInstance 
0.079245090484619 
mbstring 
0.081080913543701 
preg_split 
0.043133974075317 
htmlspecialchars 
0.25599694252014 
byte maniplulation 
0.13132810592651 

बेंचमार्क कोड यहां है।

$string = '主楼怎么走'; 

foreach (timer([ 
    'grapheme' => 'str_to_array', 
    'IntlBreakIterator::createCharacterInstance' => 'str_to_array2', 
    'IntlBreakIterator::createCodePointInstance' => 'str_to_array3', 
    'mbstring' => 'str_to_array4', 
    'preg_split' => 'str_to_array5', 
    'htmlspecialchars' => 'str_to_array6', 
    'byte maniplulation' => 'str_to_array7' 
], 
[$string]) as $desc => $time) { 

    echo $desc, PHP_EOL, 
     $time, PHP_EOL; 
} 

function timer(array $callables, array $arguments, $repeat = 10000) { 

    $ret = []; 
    $save = $repeat; 

    foreach ($callables as $key => $callable) { 

     $start = microtime(true); 

     do { 

      array_map($callable, $arguments); 

     } while($repeat -= 1); 

     $stop = microtime(true); 
     $ret[$key] = $stop - $start; 
     $repeat = $save; 

    } 

    return $ret; 
} 
संबंधित मुद्दे