Использование Regex для подсчета словосочетаний в тексте Аннотация с использованием VB.net - PullRequest
0 голосов
/ 14 марта 2020

У меня есть медицинский словарь терминов, и эти термины могут быть комбинацией слов, таких как: [ Рак молочной железы или Рак простаты ] Или единичные, такие как [ Грудь и Простата и Рак ] или даже [ бета-клеточная опухоль поджелудочной железы ].

Мне нужно сосчитать слова в реферат статьи, которые есть в словаре, не считая их дважды, поэтому если я считаю рак молочной железы как

  1. , я не должен считать грудь или Рак индивидуально, когда они появляются вместе как дополнительный
  2. Я извлекаю слова из базы данных MS SQL, где я добавил столбец, который подсчитывает пробел между словами и сортируется по наибольшему до самых маленьких, а затем слово.

Что мне нужно сделать, так это когда я считаю слово, заменяю его пробелом или "", чтобы оно не было доступно для индивидуального подсчета. Меня не волнует текст в аннотации, который всегда можно обновить после.

Мой код VB. net в. Net WEB API:

While reader.Read '- -pulling words from database

    word = reader("Word").ToString

    Dim regex As Regex

    If word.StartsWith("ER") Then
        regex = New Regex("\s" + word + "\s", RegexOptions.None)
    Else
        regex = New Regex("\s" + word + "\s", RegexOptions.IgnoreCase)
    End If

    Dim regex As Regex = New Regex("\b(" + word + ")\b", RegexOptions.IgnoreCase)
    Dim match As Match = regex.Match(abstractText)
    If match.Success Then
        TotalAbstractCount += regex.Matches(abstractText).Count
        abstractCount += 1
        abstractWords.Add(word)
        abstractWordsCount.Add(word + " (" + count.ToString + ")")
        ' new code added to replace word/word string with blank
        Dim regex2 = New Regex(word, RegexOptions.IgnoreCase)
        abstractText = regex2.Replace(abstractText, " ")

    End If
    match = match.NextMatch()

End While

Используя этот код, есть ли место, где я могу обновить совпадение до пустой строки? Или мне нужно собрать al oop?

ОБНОВЛЕНИЕ: я просто добавил новый код regex2, но поскольку он вызывает новый regex для каждого слова, кажется, он замедляет весь процесс. Конечный пользователь ждет в режиме реального времени результатов. Весь процесс я не рассчитал, но похоже, что он увеличился с 1-1,5 секунды до 3-4.

Кроме того, если есть более быстрый способ сделать это на сервере MS SQL 2016 I Я открыт для этого.

1 Ответ

0 голосов
/ 15 марта 2020

Вот мой (относительно непроверенный) ответ.

Алгоритм:

  • получить фразы
  • получить текст
  • очистить текст, превращающий все, что не является символом слова, в пробел
  • l oop фраз, поиск " phrase " (длина 8) и замену пробелами " " (длина 7) - изменение длины количество вхождений
Imports System.Text.RegularExpressions
Imports System.Text
Imports System.Collections.Generic
Imports System
Imports System.Linq

Public Module Module1
    Public Sub Main()

        Dim phrases() as String  = { "brEast", "bREast canCer", "caNCer" }

        Dim text as String = "Breast- cAncer is Cancer!! of .the breAst. we need to keep aBREAST of it as it is CANCERous. Breast Cancer is bad cancer"

        Dim cleaner  = new Regex("\W+")

        'remove all non word characters, replacing them with a single space
        Dim cleanText = cleaner.Replace(text, " ")

        'put the text into a stringbuilder for much faster string manipulation
        'add space at the start and end - spaces delimit words for us
        Dim textSb as New StringBuilder(" " & cleanText.ToLower() & " ")

        'something to hold the counts of phrases
        Dim counts = New Dictionary(Of String, Integer)

        'Sort phrases from long to short, prevents "breast" ruining "breast cancer"
        Dim orderedPhrases = phrases.OrderByDescending(Function(p As String) p.Length)

        For Each phrase as String in orderedPhrases

            'capture the old length - we'll need this
            Dim prevLen as Integer = textSb.Length

            'replace all occurrences of the phrase in the text.
            'tack a space onto either end of the phrase to find whole words only

            'because the replacement str is 1 shorter than the find
            'the count of replacements is simply the change in length

            'also we need the replacement string to be spaces
            'because we rely on spaces at the start and end of a
            'find string to delimit a phrase. removing all spaces
            'could break our logic. If we replace with nothing:
            '"type 1 breast cancer cancer is bad" -> "type 1cancer is bad"
            'then we cannot now find " cancer "

            Dim findPhrase = " " & phrase.ToLower() & " "
            Dim replPhrase = new String(" ", findPhrase.Length - 1)
            textSb.Replace(findPhrase, replPhrase)

            'store the count of occurrences of this phrase
            counts(phrase) = prevLen - textSb.Length

        Next phrase

        'let's print our counts as proof it works
        For Each key as String in counts.Keys
            Console.Out.WriteLine(key  & " count is " & counts(key))
            Next key


    End Sub
End Module

У меня нет большого набора данных, чтобы попробовать его, но я запустил весь этот метод 100 000 раз за 2,5 секунды

https://dotnetfiddle.net/xxlpde

Примечание: если вы делаете это для большого количества текстов (например, как oop набора текстов), вы можете предварительно отсортировать фразы:

Dim orderedPhrases = phrases.OrderByDescending(Function(p As String) p.Length).Select(Function(p as String) " " & s.ToLower() & " ").ToArray()

Естественно, тогда findPhrase просто становится phrase, потому что мы уже добавили к нему пробелы и ToLower () отредактировали его

...