Domanda

Sto cercando di dividere il testo in parole:

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

che funziona abbastanza bene con le stringhe ma sono bloccato in alcuni casi in cui ho a che fare con i numeri.

es. Se ho il testo "Guarda questo. Il mio punteggio è 3,14 e ne sono felice." Ora l'array è

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

Quindi anche il 3.14 è diviso in 3 e 14, cosa che non dovrebbe accadere nel mio caso. Voglio dire punto dovrebbe dividere due stringhe ma non due numeri. Dovrebbe essere come:

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

Ma non ho idea di come evitare questi casi!

Qualcuno ha idea di come risolvere questo problema?

Grazie, Granit

È stato utile?

Soluzione

O usa regex :)

<?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"
}

Altri suggerimenti

Dai un'occhiata a strtok . Ti consente di modificare i token di analisi in modo dinamico, in modo da poter spezzare la stringa manualmente in un ciclo while, spingendo ogni parola divisa in un array.

La mia prima idea è stata preg_match_all ('/ \ w + /', $ stringa, $ corrispondenze); ma questo ha dato un risultato simile a quello che hai. Il problema è che i numeri separati da un punto sono molto ambigui. Può significare sia il punto decimale sia la fine della frase, quindi abbiamo bisogno di un modo per cambiare la stringa in modo tale da eliminare il doppio significato.

Ad esempio in questa frase abbiamo diverse parti che vorremmo mantenere come una sola parola: " Guarda questo. Il mio punteggio è 3.14 e ne sono felice. Non è 334,3 e oggi non è il 12-12-2009 11: 12: 13. " .

Iniziamo costruendo un dizionario di ricerca > sostituisci per codificare le eccezioni in qualcosa che non verrà diviso:

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

Successivamente, codifichiamo le eccezioni:

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

Dividi la stringa:

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

E riconvertire la parola codificata:

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

$ match ora contiene la frase originale divisa in parole con le giuste eccezioni.

Puoi rendere la regex usata in eccezioni semplice o complessa come desideri, ma alcune ambiguità passeranno sempre attraverso, ad esempio due frasi con la prima che termina e la successiva che inizia con un numero: Il numero del conteggio deve essere solo 3.3 e nient'altro che 3.5 è appena uscito.

Usa " ;. " ;, invece di ". " ;, in $ delimiterList .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top