Question

J'essaie de scinder le texte en mots:

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

qui fonctionne assez bien avec des chaînes mais je suis coincé dans certains cas où je dois faire avec des chiffres.

E.g. Si j’ai le texte "Regarde ça. Mon score est de 3.14 et j’en suis heureux." Maintenant, le tableau est

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

Ensuite, le 3.14 est divisé en 3 et 14, ce qui ne devrait pas arriver dans mon cas. Je veux dire que point devrait diviser deux chaînes mais pas deux nombres. Ce devrait être comme:

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

Mais je n'ai aucune idée de comment éviter ce cas!

Quelqu'un sait-il comment résoudre ce problème?

Merci, Granit

Était-ce utile?

La solution

Ou utilisez 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"
}

Autres conseils

Consultez strtok . Il vous permet de modifier dynamiquement les jetons d’analyse afin que vous puissiez séparer la chaîne manuellement dans une boucle while, en poussant chaque mot séparé dans un tableau.

Ma première idée a été preg_match_all ('/ \ w + /', $ string, $ matches); , mais cela donne un résultat similaire à celui que vous avez. Le problème est que les nombres séparés par un point sont très ambigus. Cela peut signifier à la fois le point décimal et la fin de la phrase, nous avons donc besoin d’un moyen de changer la chaîne de manière à éliminer le double sens.

Par exemple, dans cette phrase, nous aimerions garder un seul mot en plusieurs parties: "Regardez ceci.Ma score est de 3.14, et j'en suis heureux. Ce n'est pas le 334,3 et celui d'aujourd'hui, pas le 2009-12-12 11: 12: 13. ".

Nous commençons par créer un dictionnaire de recherche - > remplacer pour coder les exceptions en quelque chose qui ne va pas être scindé:

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

Ensuite, nous encodons les exceptions:

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

Fractionner la chaîne:

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

Et reconvertissez le mot encodé:

$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 contient maintenant la phrase d'origine divisée en mots avec les exceptions appropriées.

Vous pouvez rendre les expressions rationnelles utilisées dans les exceptions aussi simples ou complexes que vous le souhaitez, mais certaines ambiguïtés persisteront, par exemple deux phrases avec la première se terminant et la suivante commençant par un nombre: Le nombre du décompte ne doit être que de 3,3 et seul le 3.5 est sorti.

Utilisez " ;. ", au lieu de ". ", dans $ delimiterList .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top