我刚刚开始学习python。我想在NLTK中编写一个程序,将文本分成unigrams,bigrams。 例如,如果输入文本是:
"由于错误而感到悲伤和失望"
函数应该生成如下文本:
我是 - >感觉 - >感到悲伤 - >悲伤和 - >和失望 - >因为 - >因为错误而导致错误
我已编写代码将文本输入程序。这是我尝试的功能:
def gen_bigrams(text):
token = nltk.word_tokenize(review)
bigrams = ngrams(token, 2)
#print Counter(bigrams)
bigram_list = ""
for x in range(0, len(bigrams)):
words = bigrams[x]
bigram_list = bigram_list + words[0]+ " " + words[1]+"-->"
return bigram_list
我得到的错误是......
for x in range(0, len(bigrams)):
TypeError: object of type 'generator' has no len()
当ngram函数返回一个生成器时,我尝试使用len(list(bigrams))
,但它返回0值,所以我得到了相同的错误。我已经提到了有关stackexchange的其他问题,但我仍然没有解决如何解决这个问题。我被这个错误困住了。任何解决方法,建议?。
答案 0 :(得分:4)
通过连接由分隔符分隔的值来构造字符串最好由str.join
:
def gen_bigrams(text):
token = nltk.word_tokenize(text)
bigrams = nltk.ngrams(token, 2)
# instead of " ".join also "{} {}".format would work in the map
return "-->".join(map(" ".join, bigrams))
请注意,没有尾随“ - >”,因此,如果有必要,请添加。这样你甚至不必考虑你正在使用的可迭代的长度。一般来说,在python中几乎总是如此。如果要迭代迭代,请使用for x in iterable:
。如果确实需要索引,请使用enumerate
:
for i, x in enumerate(iterable):
...
答案 1 :(得分:1)
bigrams是一个生成器函数,bigrams.next()可以为你提供令牌的元组。 您可以在bigrams.next()上执行len(),但不能在生成器函数上执行。以下是更复杂的代码,可以实现您想要实现的目标。
>>> review = "i am feeling sad and disappointed due to errors"
>>> token = nltk.word_tokenize(review)
>>> bigrams = nltk.ngrams(token, 2)
>>> output = ""
>>> try:
... while True:
... temp = bigrams.next()
... output += "%s %s-->" % (temp[0], temp[1])
... except StopIteration:
... pass
...
>>> output
'i am-->am feeling-->feeling sad-->sad and-->and disappointed-->disappointed due-->due to-->to errors-->'
>>>