从 re.findall(regex, text) 改为 nltk.Text.findall(regex)
我用Python和NLTK库写了一个正则表达式,目的是找到文本中以大写字母开头但不在句子开头的单词。
最开始我这样使用它:
[w for w in text if re.findall(r'(?<!\.\s)\b[A-Z][a-z]\b',w)]
变量text是用treebank语料库创建的,具体如下:
>>> def concat(lists):
biglist = [ ]
while len(lists)>0:
biglist = biglist+lists[0]
lists=lists[1:]
return biglist
>>> tbsents = concat(treebank.sents()[200:250])
>>> text = nltk.Text(tbsents)
不过,这样似乎不太管用,它还是会返回那些在句子开头的单词。所以我想试试用text.findall()这个函数。
我运行了以下代码,它成功返回了所有以大写字母开头的单词,正是我需要的。
>>> text.findall("<[A-Z][a-z]{3,}>")
我现在的问题是,我不知道怎么把正则表达式的第一部分转换成第二个函数需要的<..>格式,如果我能做到,这样做是否有效,还是我完全走错了方向?
谢谢。
1 个回答
2
我不太明白你在第一个列表推导式中做了什么:你是在每个单独的单词上使用findall,而不是在整个文本上。
如果你想处理树库语料库,既然你已经按句子分好了,最简单的方法是:
import itertools
non_starting_words = list(itertools.chain(*[s[1:] for s in treebank.sents()]))
uppercase_words = [w for w in non_starting_words if w[0].isupper()]
也许这就是你想用“concat”函数做的事情,但那样只是得到了所有单词的列表,并没有去掉每个句子的第一个单词。如果你确实想把多个列表合并在一起,使用我上面提到的list(itertools.chain(*lists))会更好。
补充一下:既然你需要处理一个标记的列表,最好的解决方案就不是使用正则表达式,而是:
punctuation_marks = ".!?"
first_word = True
uppercase_words = []
for w in text:
if not first_word and re.match("[A-Z][a-z]*$", w):
uppercase_words.append(w)
first_word = w in punctuation_marks
print uppercase_words