2013-06-15 3 views
3

Мне нужно получить первые N предложений из текста, где последний символ предложения может быть периодом, двоеточием или точкой с запятой. Например, если этот текст:Как получить первые N предложений из текста?

Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor. 
incididunt ut labore: et dolore magna aliqua. Ut enim ad. minim veniam. 

Первые 4 предложения будет,

Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor. 
incididunt ut labore: 

В настоящее время мой код разделения строки, используя ., : и ; в качестве разделителя, а затем присоединиться к Результаты.

import re 
sentences = re.split('\. |: |;', text) 
summary = ' '.join(sentences[:4]) 

Но он удалит разделители из результата. Я открыт для регулярного выражения или базовых манипуляций с строкой.

+1

Как вы относитесь к: _For, например, It's 5 A.M. утром здесь и моей C.D. не работает очень хорошо и т. д. и т. д .; ты в порядке. с этим?_? – Ben

+0

@Ben да, есть «особые случаи», и результат является приемлемым. Он не должен быть полностью совершенным. – flowfree

ответ

4
>>> import re 
>>> text = "Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor. incididunt ut labore: et dolore magna aliqua. Ut enim ad. minim veniam." 
>>> ' '.join(re.split(r'(?<=[.:;])\s', text)[:4]) 
'Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor. incididunt ut labore:' 

Нечто подобное было бы более эффективным, подстраиваться под ваши потребности при форматировании 4:

>>> re.match(r'(?:[^.:;]+[.:;]){4}', text).group() 
'Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor. incididunt ut labore:' 
+0

Он работает, спасибо! Не могли бы вы объяснить объяснение обоих регулярных выражений? – flowfree

+0

Два регулярных выражения не эквивалентны. Первый разделит только на пунктуацию + пробел, а второй - на пунктуацию (что, я считаю, это то, чего хотел OP). – Bakuriu

+0

+1 второй хороший. –

1
МОГ

пару re.finditer с itertools.islice, и строка нарезка (чтобы избежать присоединения назад и удерживая разделитель) :

import re 
from itertools import islice 

delims = re.finditer('[.:;]', s) 
try: 
    print s[:next(islice(delims, 3, None)).end()] 
except StopIteration: 
    print s # whole string instead maybe as there's not enough delimiters 
+0

@jamylak, вероятно, будет медленнее - не могу сказать, что я ее приурочил. Я просто думаю, что это, возможно, более читаемо без групп захвата и объединений и других бит и бобов ... (кроме того, вы уже приняли этот ответ :)) –

0
import re 
sentenceEnd = re.compile('[.!?][\s]{1,2}(?=[A-Z])') 
sentenceLists = sentenceEnd.split(text, re.UNICODE) 

выше Подход можно использовать то, что он будет делать, это искать период и следить за тем, чтобы следующий символ после этого был заглавной буквой и между промежутком времени и следующей буквой было пробел, это позаботится о таких случаях, как A.M. . Текст в основном там, где будет ваш исходный текст, и он будет уверен, что он будет unicoded.

3

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

Если ваша цель - наметить предложения, вам нужно искать другие инструменты. Лично я бы рекомендовал токенизатор Punkt, предоставленный nltk. Ниже приведен пример, показывающий, почему это принципиально лучший выбор, чем регулярное выражение для этой задачи.

Punkt knows that the periods in Mr. Smith and Johann S. Bach do not mark 
sentence boundaries. And sometimes sentences can start with non-capitalized 
words. i is a good variable name. 

http://nltk.org/api/nltk.tokenize.html для получения дополнительной информации.

+0

+1 для использования 'nltk' - это не идеально, но он делает удивительно хорошая работа по обнаружению конца предложений. – Aya

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