Regex в Java для поиска повторяющихся последовательных слов - PullRequest
11 голосов
/ 05 февраля 2012

Я видел это как ответ на поиск повторяющихся слов в строке. Но когда я его использую, он думает, что This и is одинаковы и удаляет is.

Regex

"\\b(\\w+)\\b\\s+\\1"

Есть идеи, почему это происходит?

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

public static String RemoveDuplicateWords(String input)
{
    String originalText = input;
    String output = "";
    Pattern p = Pattern.compile("\b(\w+)\b\s+\b\1\b", Pattern.MULTILINE+Pattern.CASE_INSENSITIVE); 
    //Pattern p = Pattern.compile("\\b(\\w+)\\b\\s+\\1", Pattern.MULTILINE+Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(input);
    if (!m.find())
        output = "No duplicates found, no changes made to data";
    else
    {
        while (m.find())
        {
            if (output == "")
                output = input.replaceFirst(m.group(), m.group(1));
            else
                output = output.replaceAll(m.group(), m.group(1));
        }
        input = output;
        m = p.matcher(input);
        while (m.find())
        {
            output = "";
            if (output == "")
                output = input.replaceAll(m.group(), m.group(1));
            else
                output = output.replaceAll(m.group(), m.group(1));
        }
    }
    return output;
}

Ответы [ 6 ]

19 голосов
/ 10 мая 2016

Попробуйте это:

String pattern = "(?i)\\b([a-z]+)\\b(?:\\s+\\1\\b)+";
Pattern r = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);

String input = "your string";
Matcher m = r.matcher(input);
while (m.find()) {
    input = input.replaceAll(m.group(), m.group(1));
}
System.out.println(input);

Регулярные выражения Java очень хорошо объяснены в документации API класса Pattern .После добавления пробелов для обозначения различных частей регулярного выражения:

"(?i) \\b ([a-z]+) \\b (?: \\s+ \\1 \\b )+"

\b       match a word boundary
[a-z]+   match a word with one or more characters;
         the parentheses capture the word as a group    
\b       match a word boundary
(?:      indicates a non-capturing group (which starts here)
\s+      match one or more white space characters
\1       is a back reference to the first (captured) group;
         so the word is repeated here
\b       match a word boundary
)+       indicates the end of the non-capturing group and
         allows it to occur one or more times
6 голосов
/ 09 декабря 2015

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

Pattern.compile("\\b(\\w+)(\\b\\W+\\b\\1\\b)*", Pattern.MULTILINE+Pattern.CASE_INSENSITIVE); 

Для e-g, "Это мой мой мой приятель приятель приятель" выдаст "Это мой приятель"

Кроме того, для этого шаблона достаточно одной итерации с параметром while (m.find ()).

6 голосов
/ 05 февраля 2012

Вы должны были использовать \b(\w+)\b\s+\b\1\b, нажмите здесь , чтобы увидеть результат ...

Надеюсь, это то, что вы хотите ...

Обновление 1

Хорошо, хорошо, у вас есть вывод

последняя строка после удаления дубликатов

import java.util.regex.*;

public class MyDup {
    public static void main (String args[]) {
    String input="This This is text text another another";
    String originalText = input;
    String output = "";
    Pattern p = Pattern.compile("\\b(\\w+)\\b\\s+\\b\\1\\b", Pattern.MULTILINE+Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(input);
    System.out.println(m);
    if (!m.find())
        output = "No duplicates found, no changes made to data";
    else
    {
        while (m.find())
        {
            if (output == "") {
                output = input.replaceFirst(m.group(), m.group(1));
            } else {
                output = output.replaceAll(m.group(), m.group(1));
            }
        }
        input = output;
        m = p.matcher(input);
        while (m.find())
        {
            output = "";
            if (output == "") {
                output = input.replaceAll(m.group(), m.group(1));
            } else {
                output = output.replaceAll(m.group(), m.group(1));
            }
        }
    }
    System.out.println("After removing duplicate the final string is " + output);
}

Запустите этот код и посмотрите, что вы получите в качестве результата ... Ваши запросы будут решены ...

Примечание

В output вы заменяете дубликат одним словом ... Не так ли?

Когда я вначале ставлю System.out.println(m.group() + " : " + m.group(1));, если при условии получаю вывод как text text : text, т.е. дубликаты заменяются одним словом.

else
    {
        while (m.find())
        {
            if (output == "") {
                System.out.println(m.group() + " : " + m.group(1));
                output = input.replaceFirst(m.group(), m.group(1));
            } else {

Надеюсь, ты понял, что происходит ...:)

Удачи !!! Ура !!!

4 голосов
/ 30 августа 2016
\b(\w+)(\b\W+\1\b)*

Пояснение:

\b : Any word boundary <br/>(\w+) : Select any word character (letter, number, underscore)

После того, как все слова выбраны, пришло время выбрать общие слова.

( : Grouping starts<br/>
\b : Any word boundary<br/>
\W+ : Any non-word character<br/>
\1 : Select repeated words<br/>
\b : Un select if it repeated word is joined with another word<br/>
) : Grouping ends

Ссылка: Пример

1 голос
/ 03 января 2019

, если важны юникоды, чем вы должны использовать это:

 Pattern.compile("\\b(\\w+)(\\b\\W+\\b\\1\\b)*",
        Pattern.MULTILINE + Pattern.CASE_INSENSITIVE + Pattern.UNICODE_CHARACTER_CLASS)
0 голосов
/ 05 февраля 2012

Я считаю, что это регулярное выражение, которое вы должны использовать для обнаружения 2 последовательных слов, разделенных любым количеством несловесных символов:

Pattern p = Pattern.compile("\\b(\\w+)\\b\\W+\\b\\1\\b", Pattern.CASE_INSENSITIVE);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...