将文本拆分为单词,并将带小数的数字视为整个“单词”

问题描述 投票:0回答:4

我正在尝试将文本拆分为单词:

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

对于字符串来说效果很好,但在某些与数字有关的情况下我遇到了困难。

例如如果我有这样的文字:“看看这个。我的分数是 3.14,我对此很高兴。”。 现在数组是

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

然后 3.14 也被分为 3 和 14,这在我的情况下不应该发生。 我的意思是点应该除两个字符串而不是两个数字。 应该是这样的:

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

但我不知道如何避免这种情况!

php split cpu-word
4个回答
9
投票

或者使用正则表达式:)

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

6
投票

看看strtok。它允许您动态更改解析标记,因此您可以在 while 循环中手动拆分字符串,将每个拆分的单词推入数组中。


1
投票

我的第一个想法是

preg_match_all('/\w+/', $string, $matches);
,但这给出了与你得到的类似的结果。问题是用点分隔的数字非常不明确。它既可以表示小数点,也可以表示句子结尾,因此我们需要一种方法来更改字符串,以消除双重含义。

例如,在这句话中,我们有几个部分希望保留为一个单词:

"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."

我们首先构建一个搜索->替换字典,将异常编码为不会被拆分的内容:

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

接下来,我们对异常进行编码:

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

分割字符串:

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

并将编码后的单词转换回来:

$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
现在包含原始句子,已拆分为单词,但有正确的例外。

您可以根据需要使异常中使用的正则表达式变得简单或复杂,但总会出现一些歧义,例如两个句子,第一个句子结尾,下一个句子以数字开头:

Number of the counting shall be 3.3 only and nothing but the 3.5 is right out..


0
投票

". ",
中使用
".",
代替
$delimiterList

© www.soinside.com 2019 - 2024. All rights reserved.