Как перебрать предложение строки в Python?

Предположим, у меня есть строка text = "A compiler translates code from a source language". Я хочу сделать две вещи:

  1. Мне нужно перебрать каждое слово и основу, используя библиотеку NLTK. Функция стемминга — PorterStemmer().stem_word(word). Мы должны передать аргумент «слово». Как я могу составить основу каждого слова и вернуть предложение, составленное из основы?

  2. Мне нужно удалить определенные стоп-слова из строки text. Список, содержащий стоп-слова, хранится в текстовом файле (через пробел).

    stopwordsfile = open('c:/stopwordlist.txt','r+')
    stopwordslist=stopwordsfile.read()
    

    Как я могу удалить эти стоп-слова из text и получить чистую новую строку?


person ChamingaD    schedule 08.05.2012    source источник
comment
стемме = для слова в text.split(' '): стеммер.стем_слово(слово) это будет работать?   -  person ChamingaD    schedule 09.05.2012
comment
Не совсем. Если вам нужен список стеблей, вы можете сделать stemmed = [stemmer.stem_word(w) for w in text.split(' ')]. Если вам нужно предложение из него, вы можете выполнить sente = ' '.join(stemmed), что вернет предложение из всех стеблей. Дайте мне знать, если это поможет.   -  person wkl    schedule 09.05.2012
comment
@birryree Спасибо :) Я сделал это с помощью .join(PorterStemmer().stem_word(word) вместо слова в text.split()))   -  person ChamingaD    schedule 09.05.2012


Ответы (2)


Я разместил это как комментарий, но подумал, что мог бы также конкретизировать его в полный ответ с некоторыми пояснениями:

Вы хотите использовать str.split(), чтобы разбить строку на слова, а затем каждое слово:

for word in text.split(" "):
    PorterStemmer().stem_word(word)

Поскольку вы хотите получить строку из всех слов, образованных от корней, тривиально затем снова соединить эти основы вместе. Чтобы сделать это легко и эффективно, мы используем str.join() и выражение генератора:

" ".join(PorterStemmer().stem_word(word) for word in text.split(" "))

Редактировать:

Для другой вашей проблемы:

with open("/path/to/file.txt") as f:
    words = set(f)

Здесь мы открываем файл с помощью инструкции with (это лучший способ открывать файлы, так как он корректно обрабатывает их закрытие, даже в исключениях, и более удобочитаем) и считывает содержимое в набор. Мы используем набор, так как нам не важен порядок слов или дубликаты, и позже он будет более эффективным. Я предполагаю, что одно слово в строке - если это не так, и они разделены запятыми или пробелами, то использование str.split(), как мы делали раньше (с соответствующими аргументами), вероятно, является хорошим планом.

stems = (PorterStemmer().stem_word(word) for word in text.split(" "))
" ".join(stem for stem in stems if stem not in words)

Здесь мы используем предложение if выражения генератора, чтобы игнорировать слова, которые входят в набор слов, загруженных из файла. Проверки членства в наборе выполняются за O(1), так что это должно быть относительно эффективно.

Редактировать 2:

Чтобы удалить слова до того, как они будут выделены, это еще проще:

" ".join(PorterStemmer().stem_word(word) for word in text.split(" ") if word not in words)

Удаление данных слов просто:

filtered_words = [word for word in unfiltered_words if not in set_of_words_to_filter]
person Gareth Latty    schedule 08.05.2012
comment
Мне нужно сделать еще одну вещь. Чтобы удалить стоп-слова из этой строки. Список стоп-слов, хранящихся в текстовом файле (через пробел) stopwordsfile = open('c:/stopwordlist.txt','r+') stopwordslist=stopwordsfile.read() Мне нужно удалить эти стоп-слова из text и очистить новую строку. - person ChamingaD; 09.05.2012
comment
@ChamingaD Я бы предположил, что это другая проблема, и вам следует открыть новый вопрос. Если вы сделаете это, это будет более полезно для других людей в будущем с похожей проблемой, и нам будет легче работать с ними. - person Gareth Latty; 09.05.2012
comment
Проблема в том, что мне нужно ждать еще 20 минут, чтобы начать новый вопрос :/ - person ChamingaD; 09.05.2012
comment
@ChamingaD Я добавил здесь ответ на этот случай. Однако в будущем размещение отдельного вопроса будет лучшим решением. - person Gareth Latty; 09.05.2012
comment
Большое спасибо :) Могу ли я удалить стоп-слова в виде отдельного кода? (сначала я удалю стоп-слова, а затем корень) - person ChamingaD; 09.05.2012
comment
@ChamingaD добавил, что в будущем вы, возможно, захотите более четко понимать, чего хотите. - person Gareth Latty; 09.05.2012
comment
Да, кажется, мое объяснение плохое :/. Мне нужны два отдельных сегмента кода для удаления стоп-слов и основ (два для циклов разделены). Потому что я должен проверить, как каждая техника влияет на конечный результат;) - person ChamingaD; 09.05.2012
comment
filtered_words = [слово в слово в unfiltered_words, если не в set_of_words_to_filter] .. В этом коде unfiltered_words = text и set_of_words_to_filter = stopwordslist ? Мой список стоп-слов разделен пробелами, будет ли это работать? - person ChamingaD; 09.05.2012

Чтобы просмотреть каждое слово в строке:

for word in text.split():
    PorterStemmer().stem_word(word)

Используйте метод объединения строк (рекомендуемый Lattyware), чтобы объединить фрагменты в одну большую строку.

" ".join(PorterStemmer().stem_word(word) for word in text.split(" "))
person Gergely Sipkai    schedule 08.05.2012
comment
В вопросе задается вопрос «и получить предложение с основой», поэтому полный ответ будет " ".join(PorterStemmer().stem_word(word) for word in text.split(" ")). - person Gareth Latty; 09.05.2012