Sözler sorun PHP, karmaşık bir sorun haline metni bölme

4 Cevap php

Ben kelimelerle metni bölmek çalışıyorum:

$delimiterList = array(" ", ".", "-", ",", ";", "_", ":",
           "!", "?", "/", "(", ")", "[", "]", "{", "}", "<", ">", "\r", "\n",
           '"');
$words = mb_split($delimiterList, $string);

hangi dizeleri ile oldukça iyi çalışıyor ama ben numaraları ile yapmak zorunda bazı durumlarda şaşırıp.

E.g. If I have the text "Look at this.My score is 3.14, and I am happy about it.". Now the array is

[0]=>Look,
[1]=>at,
[2]=>this,
[3]=>My,
[4]=>score,
[5]=>is,
[6]=>3,
[7]=>14,
[8]=>and, ....

Then also the 3.14 is divided in 3 and 14 which should not happen in my case. I mean point should divide two strings but not two numbers. It should be like:

[0]=>Look,
[1]=>at,
[2]=>this,
[3]=>My,
[4]=>score,
[5]=>is,
[6]=>3.14,
[7]=>and, ....

Ama bu davaları önlemek için nasıl hiçbir fikrim yok!

Herkes bu sorunu çözmek için nasıl bir fikir?

Thanx, Granit

4 Cevap

Ya regex kullanmak :)

<?php
$str = "Look at this.My score is 3.14, and I am happy about it.";

// alternative to handle Marko's example (updated)
// /([\s_;?!\/\(\)\[\]{}<>\r\n"]|\.$|(?<=\D)[:,.\-]|[:,.\-](?=\D))/

var_dump(preg_split('/([\s\-_,:;?!\/\(\)\[\]{}<>\r\n"]|(?<!\d)\.(?!\d))/',
                    $str, null, PREG_SPLIT_NO_EMPTY));

array(13) {
  [0]=>
  string(4) "Look"
  [1]=>
  string(2) "at"
  [2]=>
  string(4) "this"
  [3]=>
  string(2) "My"
  [4]=>
  string(5) "score"
  [5]=>
  string(2) "is"
  [6]=>
  string(4) "3.14"
  [7]=>
  string(3) "and"
  [8]=>
  string(1) "I"
  [9]=>
  string(2) "am"
  [10]=>
  string(5) "happy"
  [11]=>
  string(5) "about"
  [12]=>
  string(2) "it"
}

strtok bir göz atın. Bu bir diziye her ayrılarak kelimeyi iterek, bir süre döngü dışında elle dize kırmak, böylece dinamik ayrıştırma simgeleri değiştirmenizi sağlar.

Benim ilk fikriydi preg_match_all('/\w+/', $string, $matches); ama bu var birine benzer bir sonuç verir. Sorun, bir nokta ile ayrılmış sayıları çok belirsiz olmasıdır. Biz çifte anlamını ortadan kaldırmak için böyle bir şekilde dize değiştirmek için bir yol gerekir böylece ondalık noktası ve cümlenin sonuna iki anlamına gelebilir.

Bu cümlede Örneğin biz bir kelime olarak tutmak istiyorum birkaç parça var: "Look at this.My score is 3.14, and I am happy about it. It's not 334,3 and today's not 2009-12-12 11:12:13.".

Biz bölünmüş almak için gitmiyor içine bir şey istisnaları kodlamak için bir arama-> yerine sözlüğü inşa ederek başlayın:

$encode = array(
    '/(\d+?)\.(\d+?)/' => '\\1DOT\\2',
    '/(\d+?),(\d+?)/' => '\\1COMMA\\2',
    '/(\d+?)-(\d+?)-(\d+?) (\d+?):(\d+?):(\d+?)/' => '\\1DASH\\2DASH\\3SPACE\\4COLON\\5COLON\\6'
);

Sonra, istisnalar kodlamak:

foreach ($encode as $regex => $repl) {
    $string = preg_replace($regex, $repl, $string);
}

Dize bölmek:

preg_match_all('/\w+/', $string, $matches);

Ve kodlanmış kelime geri dönüştürmek:

$decode = array(
    'search' =>  array('DOT', 'COMMA', 'DASH', 'SPACE', 'COLON'),
    'replace' => array('.',   ',',     '-',    ' ',     ':'    )
);
foreach ($matches as $k => $v) {
    $matches[$k] = str_replace($decode['search'], $decode['replace'], $v);
}

$matches şimdi doğru istisnalar kelimeleri içine orijinal cümle bölünmüş içerir.

Sen basit veya istediğiniz kadar karmaşık istisnalar kullanılan regex yapabilir, ancak bazı belirsizlik her zaman sona ilki ve bir sayı ile başlayan bir sonraki örneğin, geçmek için iki sentances gidiyor: {[(0) }]

". ", yerine ".", içinde kullanın $delimiterList.