2016-04-28 4 views
4

Я только начал изучать python. Я хочу написать программу в NLTK, которая разбивает текст на униграммы, bigrams. Например, если входной текст:Объект типа 'generator' не имеет len()

«Я чувствую себя грустно и разочарование из-за ошибки»

Функция должна генерировать текст, как:

Я -> чуствую -> грустить -> печально и -> и разочаровано -> отклонено из-за -> до ошибок

Я написали код для ввода текста в программу. Вот функция, которую я пытаюсь:

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, но я все еще не понимаю, как это решить. Я застрял в этой ошибке. Любое обходное решение, предложение ?.

+3

Если 'LEN (список (биграммы))' возвращает '0', то это по-видимому вопрос ... Вы, вероятно, нужно выяснить, почему 'ngrams (маркер , 2) 'не возвращает никаких значений. – jmetz

+0

... и обновить заголовок вопроса и текст соответственно; на данный момент заголовок вводит в заблуждение – jmetz

+1

'for x in bigrams' должен работать. Тогда нет необходимости в 'words = bigrams [x]'. Зачем? 'x' будет вашим' words' –

ответ

3

Построение строк по конкатенации значений, разделенных сепаратором лучше всего сделать 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

bigrams - это функция генератора, а bigrams.next() - это то, что дает вам кортеж ваших жетонов. Вы можете сделать len() на bigrams.next(), но не на функцию генератора. Ниже приведен более сложный код, чтобы сделать то, что вы пытаетесь достичь.

>>> 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-->' 
>>> 
+1

Это должно быть просто 'для w1, w2 в битрамах:' или 'next (bigrams)' , если вручную извлекать значения из итератора (например, для получения контрольного значения).'except StopIteration:' почти всегда признак того, что что-то не так. –

Смежные вопросы