【问题标题】:regex expression - specifying number of repeated character value in a string正则表达式 - 指定字符串中重复字符值的数量
【发布时间】:2010-08-26 20:26:55
【问题描述】:

如何检查某个模式是否出现了一定次数?

例如:

4444444 => return 4

4444332 => return 4

4444431 => return 4

4443333 => return 0

4243424 => return ?

但如果字符 4 出现少于 4 次则返回 0

我只是在这里寻找4。如果出现超过或等于 4 次,则返回值为 4。字符串中的其他 3 个数字的范围只能是 1 到 3。

谢谢。

【问题讨论】:

  • 这本来可以更清楚...您只是在寻找四个或更多的四个吗?如果有四个三分怎么办?如果是这样,答案是什么,4 还是 3?如果你有四个三和四个四(或者字符串总是 7 个字符)怎么办?如果四位不在字符串的开头怎么办?你能有两个四,然后是别的东西,然后再有两个四吗?
  • 正如 Amadan 所说,问题不清楚,而且标题过于笼统 - 请更正这些。
  • 谢谢。我编辑了上面的帖子。很抱歉造成混乱
  • 好的,我已经添加了更多示例来澄清,但是您能否确认 4343434 应该返回 4 还是 0 ?
  • 应该返回一个 4. 并且它不需要是连续的 4

标签: java regex


【解决方案1】:

如果您需要四个连续的 4,则只需 4{4}4444。如果它们不需要连续,4.*4.*4.*4 会这样做。如果它可以是任意数字,但必须是四次,那么 ([1-4])\1{3}([1-4]).*\1.*\1.*\1 取决于您是否需要它们连续。

【讨论】:

  • Pattern.matches("4.*4.*4.*4.*[1-4]", inputString) 这行得通!谢谢:)
  • 应该是Pattern.matches("4.*4.*4.*4", inputString)Pattern.matches("([1-4]).*\1.*\1.*\1", inputString)
  • 现在这个有灾难性的回溯。不要像这样滥用.*。尽可能更具体(例如在这种情况下)。
  • Pattern.matches("([1-4]).*\1.*\1.*\1", inputString),一直在找这个表达式。会检查的
【解决方案2】:

要检查 1 到 4 之间的 4 个连续相同数字,您可以使用正则表达式:

([1-4])\1{3}

【讨论】:

    【解决方案3】:

    看起来^[1-3]*4[1-3]*4[1-3]*4[1-3]*4[1-4]*$ 是你基本需要的。

    匹配'4' 4 次,由 1-3 的数字包围。最后一种情况基本上是说,在 4 匹配 4 次之后,可以有任何数字 1-4 直到字符串的末尾。这适用于您上面建议的模式。上述表达式的问题在于,如果出现故障,并且您的字符串很长(>100 个字符),那么您可能会拥有所谓的Catastrophic Backtracking(参见下面的 cmets...)。为避免这种情况,您将需要 占有 匹配器,或更普遍支持的独立子表达式。这看起来像(注意,你也可以使用所有格匹配器 *+ 等):

    ^(?>[1-3]*)4(?>[1-3]*)4(?>[1-3]*)4(?>[1-3]*)4(?>[1-4]*)$
    

    【讨论】:

    • “贪婪”是量词的默认行为;添加+*+++ 等)会使它们占有。但是灾难性的回溯在这里不是问题,因为不同量词所涵盖的“领土”没有重叠。例如,第一个[1-3]* 永远不会尝试匹配与第二个[1-3]* 相同的字符,因为它们之间必须有一个4。如果您使用[0-9]*.* 而不是[1-3]*,您可能会遇到问题。
    • 当然,使用所有格量词或原子组没有危害,它们确实使正则表达式更有效,因为它不必保存状态信息使回溯成为可能。
    • 啊,是的,所有格是我要找的词。你是对的,在这种情况下,没有“灾难性”的回溯,只有在出现错误时不必要的回溯。一个非常长的字符串,最后有一个“坏”字符,需要更多的步骤。我承认这对我来说可能有点误导。感谢您提供信息丰富的评论!
    【解决方案4】:

    然后,计算模式:

    public static void main(String[] args)
    {
        String input = "44444123444441234444";
        Pattern pattern = Pattern.compile("4444");
        Matcher matcher = pattern.matcher(input);
        int count = 0;
        int lookupPosition = 0;
    
        while (matcher.find(lookupPosition))
        {
            count++;
            lookupPosition = matcher.start() + 1;
        }
    
        System.out.println(count);
    }
    

    【讨论】:

    • 嗯...这是不正确的,因为 find 并不期望模式也从指定位置开始。没那么容易。
    • 我读的太快了。您不是要求计算模式,而只是检测它并返回重复的字符,对吗?那么“1111222233334444”应该返回吗? 1? 1234?您的问题需要解决。
    • 字符串的长度只有 7。我只想找到重复 4 的模式
    • 好的,那就是:String input = "44414111"; if (input.matches(".*4.?4.?4.?4.*")) { System.out.println("4"); } else { System.out.println("0"); }
    【解决方案5】:

    您可以使用模式"(4[^4]*){4}"

      List<String> inputs = Arrays.asList("4444444", "4444332", "4443333", 
          "4243424", "4444431");
      Pattern pattern = Pattern.compile("(4[^4]*){4}");
      for(String input: inputs) {
        Matcher matcher = pattern.matcher(input);
        System.out.printf("Min 4 fours in '%s'? %b\n", input, matcher.find());
      }
    

    输出:

    Min 4 fours in '4444444'? true
    Min 4 fours in '4444332'? true
    Min 4 fours in '4443333'? false
    Min 4 fours in '4243424'? true
    Min 4 fours in '4444431'? true
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-23
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多