Поток кода Python не работает должным образом?

Я пытаюсь обрабатывать различные тексты с помощью регулярных выражений и NLTK Python, которые находятся по адресу http://www.nltk.org/book-. Я пытаюсь создать генератор случайного текста, и у меня возникла небольшая проблема. Во-первых, вот мой поток кода:

  1. Введите предложение в качестве входных данных — это называется триггерной строкой и назначается переменной.

  2. Получить самое длинное слово в строке триггера

  3. Искать во всей базе данных Project Gutenberg предложения, содержащие это слово, независимо от заглавных и строчных букв.

  4. Верните самое длинное предложение, в котором есть слово, о котором я говорил на шаге 3.

  5. Добавьте предложение на шаге 1 и шаге 4 вместе

  6. Назначьте предложение на шаге 4 новым «триггерным» предложением и повторите процесс. Обратите внимание, что я должен получить самое длинное слово во втором предложении и продолжать в том же духе и так далее.

Пока мне удалось это сделать только один раз. Когда я пытаюсь продолжить, программа продолжает печатать только первое предложение, которое дает мой поиск. На самом деле он должен искать самое длинное слово в этом новом предложении и продолжать применять мой поток кода, описанный выше.

Ниже приведен мой код вместе с образцом ввода/вывода:

Пример ввода

«Тан кода»

Пример вывода

"Тан кодекса Норвегия сам, с ужасным числом, С помощью самого нелояльного Предателя, Тана Кавдора, начал унылый Конфликт, Пока жених Беллоны, купающийся в доказательствах, Противостоял ему с самосравнениями, Точкой против точки, мятежный Арме побеждал Арме, Обуздывая свой сластолюбивый дух: и, в заключение, Победа пала на нас».

Теперь это должно фактически взять предложение, начинающееся с «самой Норвегии….», и найти в нем самое длинное слово, выполнить шаги, описанные выше, и т. д., но это не так. Какие-либо предложения? Спасибо.

import nltk

from nltk.corpus import gutenberg

triggerSentence = raw_input("Please enter the trigger sentence: ")#get input str

split_str = triggerSentence.split()#split the sentence into words

longestLength = 0

longestString = ""

montyPython = 1

while montyPython:

    #code to find the longest word in the trigger sentence input
    for piece in split_str:
        if len(piece) > longestLength:
            longestString = piece
            longestLength = len(piece)


    listOfSents = gutenberg.sents() #all sentences of gutenberg are assigned -list of list format-

    listOfWords = gutenberg.words()# all words in gutenberg books -list format-
    # I tip my hat to Mr.Alex Martelli for this part, which helps me find the longest sentence
    lt = longestString.lower() #this line tells you whether word list has the longest word in a case-insensitive way. 

    longestSentence = max((listOfWords for listOfWords in listOfSents if any(lt == word.lower() for word in listOfWords)), key = len)
    #get longest sentence -list format with every word of sentence being an actual element-

    longestSent=[longestSentence]

    for word in longestSent:#convert the list longestSentence to an actual string
        sstr = " ".join(word)
    print triggerSentence + " "+ sstr
    triggerSentence = sstr

person sarevok    schedule 26.08.2010    source источник
comment
Ваш код на самом деле в основном работает, но ужасно неясен. Я переделываю его, ответ будет в ближайшее время.   -  person msw    schedule 26.08.2010
comment
Я настоятельно рекомендую вам изучить некоторые основы Python, прежде чем запутаться в nltk; нужно ползать, прежде чем ты сможешь ходить или бегать.   -  person msw    schedule 26.08.2010


Ответы (4)


Ответ г-на Ханкина более элегантен, но следующее больше соответствует подходу, с которого вы начали:

import sys
import string
import nltk
from nltk.corpus import gutenberg

def longest_element(p):
    """return the first element of p which has the greatest len()"""
    max_len = 0
    elem = None
    for e in p:
        if len(e) > max_len:
            elem = e
            max_len = len(e)
    return elem

def downcase(p):
    """returns a list of words in p shifted to lower case"""
    return map(string.lower, p)


def unique_words():
    """it turns out unique_words was never referenced so this is here
       for pedagogy"""
    # there are 2.6 million words in the gutenburg corpus but only ~42k unique
    # ignoring case, let's pare that down a bit
    for word in gutenberg.words():
        words.add(word.lower())
    print 'gutenberg.words() has', len(words), 'unique caseless words'
    return words

print 'loading gutenburg corpus...'
sentences = []
for sentence in gutenberg.sents():
    sentences.append(downcase(sentence))

trigger = sys.argv[1:]
target = longest_element(trigger).lower()
last_target = None

while target != last_target:
    matched_sentences = []
    for sentence in sentences:
        if target in sentence:
            matched_sentences.append(sentence)

    print '===', target, 'matched', len(matched_sentences), 'sentences'
    longestSentence = longest_element(matched_sentences)
    print ' '.join(longestSentence)

    trigger = longestSentence
    last_target = target
    target = longest_element(trigger).lower()

Однако, учитывая ваше типовое предложение, оно достигает фиксации за два цикла:

$ python nltkgut.py Тейн кода
загружает корпус Гутенбурга...
=== цель Тейн сопоставил 24 предложения
сам Норвегия, с ужасными числами, с помощью самого нелояльного предателя, тана Кавдора, начался унылый конфликт , пока жених этой беллоны , одетый в proofe , не столкнул его с самосравнением , точкой против точки , мятежным arme 'gainst arme , обуздав его хвалебный дух : и, наконец, победа пала на vs
=== целевой жених сопоставил 1 предложение
Сам Норвегия , с ужасным числом , с помощью этого самого нелояльного предателя , тана Кавдора , начал унылый конфликт , пока жених этой Беллоны , купающийся в доказательствах , не столкнул его с собой . -- сравнения , пункт против пункта , мятежный arme 'gainst arme , обуздание его праздного духа : и в заключение , победа пала на vs.

Часть проблемы с ответом на последнюю проблему заключается в том, что он сделал то, что вы просили, но вы задали более конкретный вопрос, чем вы хотели получить ответ. Таким образом, ответ увяз в некоторых довольно сложных выражениях списка, которые я не уверен, что вы поняли. Я предлагаю вам более свободно использовать операторы печати и не импортировать код, если вы не знаете, что он делает. Разворачивая выражения списка, я обнаружил (как уже отмечалось), что вы никогда не использовали список слов корпуса. Функции также помогают.

person msw    schedule 26.08.2010
comment
Должен признаться, я начал заниматься Python немного поспешно, потому что в настоящее время я занимаюсь этим параллельно с летней стажировкой. Спасибо за советы и ответ. - person sarevok; 26.08.2010

Как насчет этого?

  1. Вы нашли самое длинное слово в триггере
  2. Вы найдете самое длинное слово в самом длинном предложении, содержащем слово, найденное в 1.
  3. Слово 1. является самым длинным словом предложения 2.

Что просходит? Подсказка: ответ начинается с «Бесконечно». Чтобы решить эту проблему, вы можете найти набор слов в нижнем регистре, который будет полезен.

Кстати, когда вы думаете, что MontyPython становится False и программа завершается?

person Tony Veijalainen    schedule 26.08.2010

Вместо того, чтобы каждый раз просматривать весь корпус, может быть быстрее построить единую карту от слова до самого длинного предложения, содержащего это слово. Вот моя (непроверенная) попытка сделать это.

import collections
from nltk.corpus import gutenberg

def words_in(sentence):
    """Generate all words in the sentence (lower-cased)"""
    for word in sentence.split():
        word = word.strip('.,"\'-:;')
        if word:
            yield word.lower()

def make_sentence_map(books):
    """Construct a map from words to the longest sentence containing the word."""
    result = collections.defaultdict(str)
    for book in books:
        for sentence in book:
            for word in words_in(sentence):
                if len(sentence) > len(result[word]):
                    result[word] = sent
    return result

def generate_random_text(sentence, sentence_map):
    while True:
        yield sentence
        longest_word = max(words_in(sentence), key=len)
        sentence = sentence_map[longest_word]

sentence_map = make_sentence_map(gutenberg.sents())
for sentence in generate_random_text('Thane of code.', sentence_map): 
    print sentence
person Community    schedule 26.08.2010
comment
+1 действительно элегантно, но саревок должен принять к сведению утверждение yield и прочитать о генераторах. - person msw; 26.08.2010

Вы назначаете «split_str» вне цикла, поэтому он получает исходное значение, а затем сохраняет его. Вам нужно назначить его в начале цикла while, чтобы он каждый раз менялся.

import nltk

from nltk.corpus import gutenberg

triggerSentence = raw_input("Please enter the trigger sentence: ")#get input str

longestLength = 0

longestString = ""

montyPython = 1

while montyPython:
    #so this is run every time through the loop
    split_str = triggerSentence.split()#split the sentence into words

    #code to find the longest word in the trigger sentence input
    for piece in split_str:
        if len(piece) > longestLength:
            longestString = piece
            longestLength = len(piece)


    listOfSents = gutenberg.sents() #all sentences of gutenberg are assigned -list of list format-

    listOfWords = gutenberg.words()# all words in gutenberg books -list format-
    # I tip my hat to Mr.Alex Martelli for this part, which helps me find the longest sentence
    lt = longestString.lower() #this line tells you whether word list has the longest word in a case-insensitive way. 

    longestSentence = max((listOfWords for listOfWords in listOfSents if any(lt == word.lower() for word in listOfWords)), key = len)
    #get longest sentence -list format with every word of sentence being an actual element-

    longestSent=[longestSentence]

    for word in longestSent:#convert the list longestSentence to an actual string
        sstr = " ".join(word)
    print triggerSentence + " "+ sstr
    triggerSentence = sstr
person Michael Patterson    schedule 26.08.2010