考虑以下带有POS标签的字符串:
It/PRP was/VBD not/RB okay/JJ or/CC funny/JJ and/CC I/NN will/MD never/RB buy/VB
from/IN them/PRP ever/RB again/RB
(It was not okay or funny and I will never buy from them ever again)
我想完成以下任务:
因此,所需的输出将是:
It was not-okay or not-funny and I will not-buy from them not-ever not-again
我的第一个想法是以我知道的方式做到这一点:在空间上爆炸字符串,然后将“/”上的每个单词分解为[JJ =>好的],然后制作一个switch语句来处理每个单词(例如JJ:连接等),但这看起来很草率。有没有人有更干净和/或更有效的方法,例如正则表达式?字符串已经过预先清理,所以它们总是只包含单词(没有标点符号,其他字符比a-z等)。
编辑:我知道,顺便说一下这种对待否定的方式的基本特征,但它足以满足我的需要。会有错误余量,但没关系:)
答案 0 :(得分:1)
让我试试。关于使用正则表达式进行处理的问题,
$s = "It/PRP was/VBD not/RB okay/JJ or/CC funny/JJ and/CC I/NN will/MD
never/RB buy/VB from/IN them/PRP ever/RB again/RB";
如果匹配,请删除副词
换句话说,删除任何“not”和“never”后跟“/ RB”。
$s = preg_replace("/(not|never)\/RB/i", "", $s);
将“not-”连接到每个后续形容词(JJ),副词(RB)或动词(过去时的VB或VBN)的开头
$s = preg_replace("/(\w+)\/(JJ|RB|VB|VBN)/", "not-$1/$2", $s);
删除所有POS标签(/ XX)
假设POS标签全部为大写
$s = preg_replace("/\/[A-Z]+/", "", $s);
(我的附加步骤)。从上面的正则表达式的结果中删除任何双重空格。
$s = preg_replace("/\s+/", " ", $s);
输出结果为:
It not-was not-okay or not-funny and I will not-buy from them not-ever not-again
如果你想否定除JJ / RB / VB / VBN之外的其他POS标签,只需修改步骤3(JJ | RB | VB | VBN)上的正则表达式。希望它有所帮助。
答案 1 :(得分:0)
我建议使用非正则表达式解决方案,因为正则表达式或非正则表达式方法需要进行多个函数调用。如果有一种方法可以用一个简单的preg_replace_callback()
来执行这项任务,我只能想象乍看起来很难理解。我的方法可能与你的原始代码非常相似(但我不知道,因为你没有发布你的代码)。
方法:(Demo)
$string='It/PRP was/VBD not/RB okay/JJ or/CC funny/JJ and/CC I/NN will/MD never/RB buy/VB from/IN them/PRP ever/RB again/RB';
$mods=['JJ','RB','VB','VBN']; // okay to prefix when called for
$omits=['not','never']; // strings to be omitted every time
$negbool=false; // states whether a negative adverb has been found
$array=explode(' ',$string);
foreach($array as $k=>&$v){ // make $v modifiable by reference
$parts=explode('/',$v);
// add prefix "not-" to strings who qualify
if($negbool && in_array($parts[1],$mods) && !in_array($parts[0],$omits)){
$v="not-{$parts[0]}";
// omit RB strings that don't qualify for prefixing
}elseif($parts[1]=='RB'){
unset($array[$k]); // remove
$negbool=true; // declare that modifiable strings should be modified from this point forward
// keep only leading substring
}else{
$v=$parts[0];
}
}
echo implode(' ',$array); // glue back together again using spaces
输出:
It was not-okay or not-funny and I will not-buy from them not-ever not-again