Извлечь первое предложение из строки текста - PullRequest
3 голосов
/ 24 сентября 2010

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

Поиск первого полного шага "."не работает, так как такие аббревиатуры, как "США", все испортят.

(Возможно, нет правильного ответа.)

Ответы [ 10 ]

9 голосов
/ 24 сентября 2010

Нет. Там нет простого трюка. Чтобы сделать это правильно, вам нужно сделать синтаксический анализ текста. Никто не может сделать это. По крайней мере, пока. По крайней мере, не в 100% случаев. Главным образом потому, что это также влечет за собой семантический анализ текста. Видите ли, вопреки тому, что думают лингвисты, которые учили вас грамматике в школе, довольно сложно составить предложение из набора правил, которым компьютер может следовать, не понимая текста.

Проведите следующие пару лет, изучая компьютерную лингвистику. Может, к тому времени появится ярлык?

Но вы можете приблизиться.

Вероятно, я бы попытался найти первый период, вопросительный знак или восклицательный знак, за которым следует пробел.

/^(.*?)[.?!]\s/

((.*?) - это не жадное регулярное выражение, чтобы убедиться, что вы действительно найдете только первое предложение.

5 голосов
/ 24 сентября 2010

Вы бы заплатили за это?Если это так, то Amazon Mechanical Turk, который обрабатывает задачи для реальных людей со скоростью, скажем, 0,01 доллара за обновление.По крайней мере, это чертовски больно от двухлетней компьютерной лингвистики.; -)

4 голосов
/ 18 октября 2015

Это не может быть сделано гарантированным образом, но это поможет вам сравниться с относительно простым выражением:

/(^.*?[a-z]{2,}[.!?])\s+\W*[A-Z]/

Начиная с начала строки (^), он не жадно ищет любое количество произвольных символов (.*?), заканчивающихся как минимум двумя строчными буквами ([a-z]{2,}) и точкой, знаком вопроса или восклицательный знак ([.!?]), за которым следуют один или несколько пробелов (\s+), ноль или несколько несловарных символов, например открывающая скобка (\W*) и заглавная буква ([A-Z]).

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

  • пишется с большой буквы, как в «США».
  • строчные, но отдельные буквы, как, например, в «например» или "то есть"
  • или сопровождаются строчными буквами, как в «Это сокращение означает аббревиатуру».

Один недостаток заключается в том, что оно не остановится, если предложение оканчивается пунктуацией в верхнем регистре или сокращением, но для простоты и эффективности это выглядит как справедливый компромисс.

1 голос
/ 01 декабря 2010

Попробуйте решение Байеса, такое как Splitta (http://code.google.com/p/splitta/) или в мире Ruby, Tactful Tokenizer (https://github.com/SlyShy/Tactful_Tokenizer).

1 голос
/ 29 сентября 2010

Как уже говорилось, простого решения не существует.

Более расширенная версия регулярного выражения может быть: /^(.*?(?<!\b\w)[.?!])\s+[A-Z0-9]/. Он не останавливается на акронимах в середине предложения (но также не, если они находятся в конце предложения ...), следующее предложение должно начинаться с заглавной буквы или цифры ....

Если вам известен список сокращений, на которых вы не хотите, чтобы ваше регулярное выражение останавливалось, вы можете добавить их как: /^(.*?(?<!\b\w|U\.S\.A|eg)[.?!])\s+[A-Z0-9]/.

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

1 голос
/ 24 сентября 2010

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

Не существует волшебного решения ... вы можете составить список всех аббревиатур и игнорировать их, когда следует полная остановка.

0 голосов
/ 11 мая 2019

Вот мое решение.

Метод учитывает символы точек внутри предложения: США и т. Д.
Также добавлен необязательный параметр для минимальной длины строки результата.

/// <summary>
/// Gets the first sentence from the text.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="minLength">The minimum length of the sentence.</param>
public static string FirstSentence(this string text, int minLength = 10)
{
    if (string.IsNullOrWhiteSpace(text))
    {
        return string.Empty;
    }

    var sentences = Regex.Split(text, @"(.[^\.\!\?]*(?>\.[^\s\.][^\.\!\?]+)*[\.\!\?]*)", RegexOptions.Multiline)
        .Where(s => !string.IsNullOrEmpty(s))
        .Select(s => s.Trim())
        .ToArray();

    var result = string.Empty;

    foreach (var s in sentences)
    {
        result = $"{result} {s}".Trim();

        if (result.Length >= minLength)
        {
            break;
        }
    }

    return result;
}
0 голосов
/ 15 апреля 2018

Вот мое решение.Вы также можете найти работающий кодовый код здесь

HTML

<div id="original">
   Lorem ipsum dolor sit amet, U.S.A adipiscing elit. Phasellus nulla magna, suscipit dapibus bibendum sit amet.
</div></br> 

<div id="results"></div>

JavaScript

var s = document.getElementById('original').innerHTML

var t = s.split('. ', 1)[0]

console.log(t)

document.getElementById('results').innerHTML = t
0 голосов
/ 11 января 2013

Можете ли вы предположить, что у сокращений нет пробелов между периодами? Если это так, это будет работать:

string.split('. ').first

, например

s = "Lorem ipsum dolor sit amet, U.S.A adipiscing elit. Phasellus nulla magna, suscipit dapibus bibendum sit amet."
s.split('. ').first

=> "Lorem ipsum dolor sit amet, U.S.A adipiscing elit"

Обратите внимание, что он удаляет завершающий период.

0 голосов
/ 24 сентября 2010

Использование простой текстовой строки - это не гарантированный способ сделать это, но использование строки с некоторой маскировкой, например, если ваша строка имеет \ n в конце каждой строки или предложения, вы можете использовать это, чтобы определить конец строкиКроме того, вы должны просто угадать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...