Поиск нескольких слов в тексте с использованием регулярных выражений (Java) - PullRequest
1 голос
/ 05 июля 2019

У меня есть метод для поиска слова в тексте, оба вставляются по аргументам.

public Integer findTheWord(String stringToCheck, String regexString) throws IOException {

        int count = 0;
        Pattern regexp = Pattern.compile("\\b" + regexString + "\\b");
        Matcher matcher = regexp.matcher(stringToCheck);

        while (matcher.find()) {
                count++;
                String matchString = matcher.group();
                System.out.println(matchString);
            }
        System.out.println(count);
        return count;
  }

Как вставить несколько слов и вернуть вхождения каждого из них?

Ответы [ 2 ]

1 голос
/ 05 июля 2019

Таким образом, первый и самый простой вариант - использовать ваш фактический метод findTheWord() и создать новый метод, который его использует:

public Map<String, Integer> findTheWords(String stringToCheck, List<String> words) {
    return words.stream().distinct()
            .collect(Collectors.toMap(Function.identity(), word -> findTheWord(stringToCheck, word)));
}

public Integer findTheWord(String stringToCheck, String regexString) {
    Pattern regexp = Pattern.compile("\\b" + regexString + "\\b");
    Matcher matcher = regexp.matcher(stringToCheck);

    int count = 0;
    while (matcher.find()) {
        count++;
    }
    return count;
}

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

public Map<String, Integer> findTheWords(String stringToCheck, List<String> words) {
    Pattern regexp = Pattern.compile(words.stream().distinct().map(word -> "\\b" + word + "\\b").collect(Collectors.joining("|")));
    // creates a pattern like this: "\ba\b|\bb\b|\bc\b|\bd\b|\be\b"
    Matcher matcher = regexp.matcher(stringToCheck);
    Map<String, Integer> result = new HashMap<>();
    while (matcher.find()) {
        String word = matcher.group();
        result.put(word, result.getOrDefault(word, 0) + 1);
    }
    return result;
}

Кроме того, что вы, возможно, рассматриваете возможность использования Set для слов вместо List, поскольку значения уникальны, поэтому нет необходимости вызывать .distinct() в потоке.

1 голос
/ 05 июля 2019

HashMap в качестве аргумента с входной строкой в ​​качестве ключа и регулярным выражением в качестве значения, циклический просмотр всех записей, выполнение вашего метода и возврат HashMap с совпавшим словом в качестве ключа и вхождениями в качестве значения.

 public HashMap<String, Integer> findTheWordsAndOccurences(HashMap<String, String> stringsAndRegex) throws IOException {

    HashMap<String, Integer> result = null;

    for (Map.Entry<String, String> entry : stringsAndRegex.entrySet()){

        String stringToCheck = entry.getKey();
        String regexString = entry.getValue();
        String matchString = "";
        int count = 0;
        Pattern regexp = Pattern.compile("\\b" + regexString + "\\b");
        Matcher matcher = regexp.matcher(stringToCheck);

        while (matcher.find()) {
            count++;
            matchString = matcher.group();
            System.out.println(matchString);
            result.put(matchString, count);
        }
    }
    return result;
}
...