Java Поиск строки содержимого для частичного соответствия - PullRequest
0 голосов
/ 12 февраля 2019

Я работаю над проектом, в котором мне нужно найти абзац текста для конкретной строки.Тем не менее, мне не нужно точное совпадение, больше совпадения%.

Например, вот текст абзаца, который я ищу:

Fluticasone Propionate Nasal Spray, USP 50 mcg per spray is a 
corticosteroid indicated for the management of the nasal symptoms of 
perennial nonallergic rhinitis in adult and pediatric patients aged 4 years 
and older."

И затем я ищу, чтобы найти, соответствуют ли слова в следующих строках абзацу:

1)Unspecified acute lower respiratory infection
2)Vasomotor rhinitis
3)Allergic rhinitis due to pollen
4)Other seasonal allergic rhinitis
5)Allergic rhinitis due to food
6)Allergic rhinitis due to animal (cat) (dog) hair and dander
7)Other allergic rhinitis
8)"Allergic rhinitis, unspecified"
9)Chronic rhinitis
10)Chronic nasopharyngitis

В моем первоначальном подходе к этому использовалось логическое значение, содержащее:

boolean found = med[x].toLowerCase().contains(condition[y].toLowerCase());

однако результаты для каждого проходного цикла отрицательные.

Ожидаемые результаты будут:

1) False
2) True
3) True
4) True
5) True
6) True
7) True
8) True
9) True
10) False

Очень плохо знакомы с Java и его методами.В принципе, если любое слово в A соответствует любому слову в B, пометьте его как trueКак я могу это сделать?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

Если вы составите список с искомыми словами, это будет намного проще.Предположим, ваш абзац хранится в виде строки:

ArrayList<String> dictionary = new ArrayList<>();
dictionary.add("acute lower respiratory infection");
dictionary.add("rhinitis");
for(int i =0; i<dictionary.size(); i++){
    if(paragraph.contains(dictionary.get(i))){
        System.out.println(i + "True");
    }
    else{
         System.out.println(i +"False");
    }
}
0 голосов
/ 12 февраля 2019

Это даст вам «сырой» процент совпадений.

Вот как это работает:

  1. Разделите текст для поиска и поисковый запрос на наборслова.Это делается путем разбиения с использованием регулярного выражения.Каждое слово преобразуется в верхний регистр и добавляется в набор.

  2. Подсчитайте, сколько слов в поисковом слове появляется в тексте.

  3. Вычислите процент слов в поисковом запросе, которые появляются в тексте.

Возможно, вы захотите улучшить это, удалив такие общие слова, как «a», «the» и т. Д.

    import java.util.Arrays;
    import java.util.Set;
    import java.util.stream.Collectors;

    public class CrudeTextMatchThingy {

        public static void main(String[] args) {
            String searchText = "Fluticasone Propionate Nasal Spray, USP 50 mcg per spray is a \n" +
                    "corticosteroid indicated for the management of the nasal symptoms of \n" +
                    "perennial nonallergic rhinitis in adult and pediatric patients aged 4 years \n" +
                    "and older.";

            String[] searchTerms = {
                "Unspecified acute lower respiratory infection",
                "Vasomotor rhinitis",
                "Allergic rhinitis due to pollen",
                "Other seasonal allergic rhinitis",
                "Allergic rhinitis due to food",
                "Allergic rhinitis due to animal (cat) (dog) hair and dander",
                "Other allergic rhinitis",
                "Allergic rhinitis, unspecified",
                "Chronic rhinitis",
                "Chronic nasopharyngitis"
            };

            Arrays.stream(searchTerms).forEach(searchTerm -> {
                double matchPercent = findMatch(searchText, searchTerm);
                System.out.println(matchPercent + "% - " + searchTerm);
            });
        }

        private static double findMatch(String searchText, String searchTerm) {
            Set<String> wordsInSearchText = getWords(searchText);
            Set<String> wordsInSearchTerm = getWords(searchTerm);

            double wordsInSearchTermThatAreFound = wordsInSearchTerm.stream()
                    .filter(s -> wordsInSearchText.contains(s))
                    .count();

            return (wordsInSearchTermThatAreFound / wordsInSearchTerm.size()) * 100.0;
        }

        private static Set<String> getWords(String term) {
            return Arrays.stream(term.split("\\b"))
                    .map(String::trim)
                    .map(String::toUpperCase)
                    .filter(s -> s.matches("[A-Z0-9]+"))
                    .collect(Collectors.toSet());
        }
    }

Вывод:

    0.0% - Unspecified acute lower respiratory infection
    50.0% - Vasomotor rhinitis
    20.0% - Allergic rhinitis due to pollen
    25.0% - Other seasonal allergic rhinitis
    20.0% - Allergic rhinitis due to food
    20.0% - Allergic rhinitis due to animal (cat) (dog) hair and dander
    33.33333333333333% - Other allergic rhinitis
    33.33333333333333% - Allergic rhinitis, unspecified
    50.0% - Chronic rhinitis
    0.0% - Chronic nasopharyngitis

Если вы не хотите указывать процент, но верно или неверно, вы можете просто сделать ...,

    boolean matches = findMatch(searchText, searchTerm) > 0.0;

Надеюсь, что этопомогает.

0 голосов
/ 12 февраля 2019

Вы должны сначала токенизировать одну из строк.То, что вы делаете сейчас, пытается соответствовать всей линии.

Примерно так должно работать:

String text = med[x].toLowerCase();
boolean found = 
  Arrays.stream(condition[y].split(" "))      
      .map(String::toLowerCase)
      .map(s -> s.replaceAll("\\W", "")
      .filter(s -> !s.isEmpty())
      .anyMatch(text::contains);

Я добавил удаление знаков препинания и любых пустых строк, чтобы у нас не было ложных совпадений с ними.(\\W на самом деле удаляет символы, которых нет в [A-Za-z_0-9], но вы можете изменить их на что угодно).

Если вам нужно, чтобы это было эффективно, потому что у вас много текста, выВозможно, вы захотите перевернуть его и использовать Set с более быстрым поиском.

private Stream<String> tokenize(String s) {
   return Arrays.stream(s.split(" "))
                .map(String::toLowerCase)
                .map(s -> s.replaceAll("\\W", "")
                .filter(s -> !s.isEmpty());                   
}

Set<String> words =  tokenize(med[x]).collect(Collectors.toSet());

boolean found = tokenize(condition[y]).anyMatch(words::contains);

Возможно, вы захотите отфильтровать stop слов, таких как to, and и т. д. Вы можете использовать список здесь и добавить дополнительный фильтр после того, который проверяет наличие пустых строк, чтобы проверить, что строка не является стоп-словом.

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