将字符串拆分为重复字符

23

我想要将字符串 "aaaabbbccccaaddddcfggghhhh" 分割成 "aaaa", "bbb", "cccc", "aa", "dddd", "c", "f" 等。

我尝试了这个方法:

String[] arr = "aaaabbbccccaaddddcfggghhhh".split("(.)(?!\\1)");

但这会消耗掉一个字符,所以使用上述正则表达式得到的结果是"aaa",然而我希望它是"aaaa",和第一个字符串相同。

我该如何实现这个?


1
@Adri1du40:我愿意考虑其他选项,但不想使用循环。 - Lokesh
请查看此问题:https://dev59.com/EW7Xa4cB1Zd3GeqPvvfd - Tofandel
我不是Java专家,但是string.split()比循环慢吗? - Amal Murali
@AmalMurali 会更难读。我不知道你,但是阅读这个正则表达式 (?<=(.))(?!\\1) 会让我感到困惑。 - Cruncher
这在 Haskell 中很容易实现:group "aaaabbbccccaaddddcfggghhhh" 返回预期结果 ["aaaa","bbb","cccc","aa","dddd","c","f","ggg","hhhh"]... - Bakuriu
1
可能是 Split regex to extract Strings of contiguous characters 的重复问题。 - maxxyme
3个回答

31

试一下这个:

String   str = "aaaabbbccccaaddddcfggghhhh";
String[] out = str.split("(?<=(.))(?!\\1)");

System.out.println(Arrays.toString(out));
=> [aaaa, bbb, cccc, aa, dddd, c, f, ggg, hhhh]

解释:我们想要将字符串按相同字符组分割,因此需要找到每个组之间的“边界”。我使用Java的正后顾语法选择前一个字符,然后使用反向引用的负向前瞻来验证下一个字符与前一个字符不同。没有实际使用任何字符,因为只使用了两个环视断言(也就是说,正则表达式是零宽度的)。


你的解决方案完美地运行了。你能否解释一下这个正则表达式是如何工作的? - Lokesh

5
在后向引用中进行捕获怎么样?
(?<=(.))(?!\1|$)

作为Java字符串:

(?<=(.))(?!\\1|$)

1
@T.J.Crowder 这里看起来没问题。你为什么认为它不起作用? - Reimeus
2
@Reimeus:因为我复制粘贴时没有进行转义。我真的希望Java有正则表达式字面量。 :-) - T.J. Crowder

1
在这里,我正在逐个字符进行检查,并在if循环中检查两个条件,即字符串不能超过长度,如果下一个字符不等于第一个字符,则继续for循环,否则换行并打印它。
for (int i = 0; i < arr.length; i++) {
    char chr= arr[i];
    System.out.print(chr);
    if (i + 1 < arr.length && arr[i + 1] != chr) {
        System.out.print(" \n");
    }
}

为了得到一个高质量的答案,@Shiva,您能否在您的回答中添加一些解释,说明代码是如何实现作者想要达到的目标的? - pczeus
我改进了@pczeus的答案。 - Py-Coder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接