2016-04-28 20 views
4

Ich habe gerade begonnen, Python zu lernen. Ich möchte ein Programm in NLTK schreiben, die einen Text in Unigramme, Bigramme bricht. Zum Beispiel, wenn der Eingabetext ist:Objekt des Typs 'Generator' hat keine len()

Funktion „I aufgrund von Fehlern traurig und enttäuscht fühle“ sollte Text erzeugen wie:

Ich bin -> fühle -> Gefühl traurig -> traurig und -> und enttäuscht -> disappointed fällig -> wegen -> zu Fehlern

Ich habe Code geschrieben, um Text in das Programm einzugeben. Hier ist die Funktion Ich versuche:

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 

Der Fehler Ich erhalte ist ...

for x in range(0, len(bigrams)): 
TypeError: object of type 'generator' has no len() 

Da die ngram Funktion einen Generator zurückkehrt, ich versucht, mit len(list(bigrams)) aber es gibt den Wert 0, Ich bekomme den gleichen Fehler. Ich habe auf andere Fragen zum Stackexchange verwiesen, aber ich verstehe immer noch nicht, wie ich das beheben kann. Ich stecke bei diesem Fehler fest. Irgendeine Problemumgehung, Vorschlag ?.

+3

Wenn 'len (Liste (Bigramme))' kehrt '0', dann vermutlich das ist die Frage ... Sie wahrscheinlich, warum 'ngrams brauchen, um herauszufinden (Token , 2) 'gibt keine Werte zurück. – jmetz

+0

... und den Titel und den Text der Frage entsprechend aktualisieren; im Moment ist der Titel irreführend – jmetz

+1

'für x in bigrams' sollte funktionieren. Dann brauchen wir keine Wörter mehr = bigrams [x] '. Warum? 'x' wird Ihre' Wörter' sein –

Antwort

3

Constructing Saiten durch durch einen Separator getrennt Werte verketten am besten durch str.join getan:

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)) 

Hinweis, dass es dann kein nachlauf sein „->“, so dass hinzufügen, wenn es notwendig ist, . Auf diese Weise müssen Sie nicht einmal über die Länge des iterierbaren Abschnitts nachdenken. Im Allgemeinen ist das bei Python fast immer der Fall. Wenn Sie iterativ iterieren möchten, verwenden Sie for x in iterable:. Wenn Sie die Indizes tun müssen, verwenden Sie enumerate:

for i, x in enumerate(iterable): 
    ... 
1

Bigramme ist eine Generatorfunktion und bigrams.next() gibt Ihnen das Tupel Ihrer Tokens. Sie können len() auf bigrams.next() ausführen, aber nicht auf die Generatorfunktion. Folgendes ist ausgefeilter Code, um das zu tun, was Sie erreichen möchten.

>>> 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

Dies sollte nur 'für w1, w2 in bigrams:' oder 'next (bigrams)' sein , wenn manuell Werte von einem Iterator abgerufen werden (um z. B. einen Sentinel-Wert zu erhalten).'außer StopIteration:' ist fast immer ein Zeichen, dass etwas nicht stimmt. –

Verwandte Themen