【问题标题】:Regex in java for finding duplicate consecutive wordsjava中的正则表达式用于查找重复的连续单词
【发布时间】:2012-02-27 04:04:45
【问题描述】:

我认为这是在字符串中查找重复单词的答案。但是当我使用它时,它认为Thisis 相同,并删除了is

正则表达式

"\\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;
}

【问题讨论】:

  • 我认为应该是:\b(\w+)\b\s+\1\b 否则它会认为 'ice' 和 'icecream' 是重复的。
  • rubular.com/r/Qr3twc03RR(我又调了一下,好像是字边界问题... \b(\w+)\b\s+\b\1\b )
  • 在末尾添加另一个单词边界对我来说非常有效。但即使没有这个,你的正则表达式也不应该匹配This is。你的问题可能出在其他地方,虽然我无法想象那会在哪里。
  • 虽然你有你的答案,但你可能会考虑改变你的方法。一个基本的分词器和一个类似 Set 的结构更容易理解并且可能更有效。
  • 正则表达式现在是正确的,但是您需要再次将所有这些反斜杠加倍。事实上,代码甚至无法编译。此外,您正在做大量不必要的工作。整个方法可以写成return input.replaceAll("(?i)\\b(\\w+)\\s+\\1\\b", "$1");

标签: java regex


【解决方案1】:

你应该使用\b(\w+)\b\s+\b\1\b,点击here查看结果...

希望这是你想要的...

更新 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 {

希望你现在知道发生了什么... :)

祝你好运!!!干杯!!!

【讨论】:

  • 谢谢,我会试试...正则表达式总是踢我的@#$
  • 仍然无法正常工作,我仍然得到 is in This is removed: \n这是一个重复的示例。使用以下代码: Pattern p = Pattern.compile("\\b(\\w+)\\b\\s+\\b\\1\\b", Pattern.MULTILINE+Pattern.CASE_INSENSITIVE); //模式 p = Pattern.compile("\\b(\\w+)\\b\\s+\\1", Pattern.MULTILINE+Pattern.CASE_INSENSITIVE);匹配器 m = p.matcher(input);
  • 如果我不使用双反斜杠,它会给出:54:非法转义字符 Pattern p = Pattern.compile("\b(\w+)\b\s+\b\1\b", Pattern .MULTILINE+Pattern.CASE_INSENSITIVE);
  • 双反斜杠是必要的,因为正则表达式是 Java 字符串文字的形式。并且请不要试图像那样将讨论带离现场。我们需要的任何源代码都应该包含在每个人都可以看到的问题中。而且@OP,代码 sn-ps 也不属于 cmets。改为编辑您的问题并将代码添加到其中。
  • 改为使用 "\\b(\\w+)\\b\\s+\\1\\b" 现在可以正常工作了。我会测试更多以确保明天。
【解决方案2】:

我相信这是您应该用来检测由任意数量的非单词字符分隔的 2 个连续单词的正则表达式:

Pattern p = Pattern.compile("\\b(\\w+)\\b\\W+\\b\\1\\b", Pattern.CASE_INSENSITIVE);

【讨论】:

    【解决方案3】:

    即使出现任意次数,以下模式也会匹配重复的单词。

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

    例如,“这是我的,我的,我的,我的,我的,伙伴的,伙伴的,伙伴的,伙伴的” 将输出“这是我的朋友”

    此外,这种模式只需要一次迭代“while (m.find())”就足够了。

    【讨论】:

      【解决方案4】:

      试试这个:

      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 documentation of the Pattern class 中有很好的解释。添加一些空格来表示正则表达式的不同部分后:

      "(?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
      

      【讨论】:

      • 答案是完美的。虽然太长了,请您详细说明正则表达式部分吗?
      • 非捕获组构造 ?: 到底在做什么?如果我删除它,它似乎对结果没有任何影响。
      • 我不知道人们为什么要投票其他答案:他们只得到一次重复,或者任何字母数字字符串而不是自然语言单词。这是正确的解决方案。请注意:有一个不需要的单词边界 \b 会增加正则表达式的成本,即:\b([a-z]+)(\s\b\1\b)+ 在我的测试中减少了大约 10% 的步骤:regex101.com/r/GVUshn/3
      【解决方案5】:
      \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
      

      参考:Example

      【讨论】:

      • 这应该是公认的答案,因为已经解释了完整的细节。
      【解决方案6】:

      如果 unicodes 比你应该使用这个重要:

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

      【讨论】:

        【解决方案7】:

        也可以试试这个只找到重复单词的正则表达式

        (?i)\\b(\\w+)(\\b\\W+\\b\\1\\b){1,}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-01-18
          • 1970-01-01
          • 1970-01-01
          • 2019-01-24
          • 2019-06-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多