2017-02-13 66 views
1

我正在使用NLTK分块,我想捕获匹配我的规则的字符串。例如NLTK:如何访问分块字符串

这里是我的输入

The stocks show 67% rise, last year it was 12% fall

我想捕捉

67% rise12% fall

词性标注上面的句子表明

('The', 'DT'), ('stocks', 'NNS'), ('show', 'VBP'), ('67', 'CD'), ('%', 'NN'), ('rise', 'NN'), (',', ','), ('last', 'JJ'), ('year', 'NN'), ('it', 'PRP'), ('was', 'VBD'), ('12', 'CD'), ('%', 'NN'), ('fall', 'NN') 

现在,我想出了一个简单的规则

Stat: {<CD><NN>(<NN>+|<VBN>|JJ)?}

效果很好,并且捕获

('67', 'CD'), ('%', 'NN'), ('rise', 'NN') 

('12', 'CD'), ('%', 'NN'), ('fall', 'NN') 

现在,我想提取被抓获的确切字符串。所以,我想

67% rise12% fall

我试图

current=[] 
for word,tag in subtree.leaves(): 
    current.append(word) 
print ' '.join(current) 

,但我得到

67 % rise12 % fall

通知空间%和数字之间。这在逻辑上是正确的,但不是所需的输出。我想要确切的字符串,因为我想知道捕获的字符串的开始和结束索引。

我该如何做到这一点?

+1

%_always_是否加入了数字,即您总是有'67%'而不是'67%'? – Chuck

+0

是的,绝对是 – AbtPst

+1

标记器不会跟踪字符串中的标记的来源,所以任何解决方案都会有些破解。我肯定会解决这个级别的问题(将简单标记与原始字符串相匹配),然后根据标记索引标识出您之后的块。 – alexis

回答

1

(可怕地哈克) 对于示例字符串和标签:

s = ('The', 'DT'), ('stocks', 'NNS'), ('show', 'VBP'), ('67', 'CD'), ('%', 'NN'), ('rise', 'NN'), (',', ','), ('last', 'JJ'), ('year', 'NN'), ('it', 'PRP'), ('was', 'VBD'), ('12', 'CD'), ('%', 'NN'), ('fall', 'NN') 
a = (('67', 'CD'), ('%', 'NN'), ('rise', 'NN')) 
c = 'The stocks show 67% rise, last year it was 12% fall' 

编辑:作为一个列表理解:

>>>c[min((c.index(i[0]) for i in a)):max((c.index(i[0]) for i in a)) + [len(i[0]) for i in a][-1]] 
>>>'67% rise' 

发现你输入的句子中出现的每个字的位置。记录每个单词的长度。

检查您希望的词类标签在您的例句中的位置。 :

position=[] 
lengths=[] 

for wordtag in a: 
    print wordtag,c.index(i[0]),wordtag[0],len(wordtag[0]) 
    position.append(c.index(wordtag[0])) 
    lengths.append(len(wordtag[0])) 

> ('67', 'CD') 16 67 2 
> ('%', 'NN') 18 % 1 
> ('rise', 'NN') 20 rise 4 

print position 
print lengths 

> [16, 18, 20] 
> [2, 1, 4] 

切片根据所需的标签的最小和最大位置的输入句子(编辑删除,如果为是不必要的)。您可以添加lengths[-1]以添加单词rise的长度。

valid = c[min(position):max(position) + lengths[-1]] 
print valid 

> [16, 18, 20] 
> [2, 1, 4] 

> 67% rise 

然后可以概括为这样的句子和语音标签的一部分的任何名单。