【别出心裁】用正则表达式处理字符串,一行代码完成一道麻烦的编程题

编程题:
给定一串字符串,要求对该字符串处理为:
连续三个相同的,比如AAA变成AA
连续两对相同的,比如AABB变成AAB

(为防止我表达不当,或者您审题失误,这里做一下解释:AAA代表的三个一样的样式,不是说从一堆字符串中找到“AAA”然后转变为“AA”,那太简单了。这里的AAA可以是“aaa”,也可以是“bbb”,更可以是“zzz”等等。同理,AABB也不是代表“AABB”)

常规思路:
对字符串挨个判断,然后符合AAA和AABB样式的,进行相应的处理:
大致这样:
下面这个解法,大致的思路是:
将字符串遍历,然后每个字符和后面的两个字符比较,如果一样,代表是AAA样式;
然后再和后面三个字符比较,如果和第二个一样,和第三个不一样,并且第三个和第四个一样,那么就是符合AABB样式,然后最后再对这些符合条件的字符串处理成AA样式和AAB样式。
中间因为穿插一些分支结构以及判断flag,让代码阅读比较费劲,这里不推荐阅读,只是了解这个思路,知道这个解法比较麻烦即可。
然后才能更能体会到文末那个“一行”代码的解法的“别出心裁”。

public class ScanString {
	public String scan(String word){
		boolean flag = true;
		while(flag){
			if(word.length()>2){
				StringBuilder stringBuilder = new StringBuilder(word);
				int n = 0;
				int m = 0;
				boolean flag1 = false;
				for(int i =0;i<word.length() - 2;i++){
					//取AAA
					if(String.valueOf(word.charAt(i)).equals(String.valuesOf(word.charAt(i+1))) && String.valueOf(word.charAt(i)).equals(String.valueOf(word.charAt(i+2)))){
						n = i;
						flag1 = true;
					}
				}
				boolean flag2 = false;
				for(int i =0;i<word.length() - 3;i++){
					//取AABB
					if(String.valueOf(word.charAt(i)).equals(String.valueOf(word.charAt(i +1))) && !String.valueOf(word.charAt(i+1)).equals(String.valueOf(word.charAt(i+2))) && String.valueOf(word.charAt(i+2)).equals(String.valueOf(word.charAt(i+3)))){
						m = i+2;
						flag2 = true;
					}
				}
				if(n!=0){
					stringBuilder.deleteCharAt(n);
				}
				if(m!=0){
					stringBuilder.deleteCharAt(m);
				}
				word = stringBuilder.toString();
				if(!flag1 && !flag2){
					flag = false;
				}
			}else{
				flag = false;
			}
		}
		return word;
	}
	
}

上面就是比较简单的思路,就是利用循环,不断的判断,判断出AAA以及AABB的,然后修改成AA以及AAB。
但是可以看出,上面的代码很长一段,并且阅读起来很费劲。
当然你可能有更多好的方法,可以让上面的代码,变成更少的行数,并且更容易阅读,但是如果用正则表达式呢?
用正则表达式,只需要一行:

public class ScanString{
	public void scan(String word){
		//只需下面一行
		word.replaceAll("(.)\\1\\1","$1$1").replaceAll("(.)\\1(.)\\2","$1$1$2");
	}
}

这种解决方式,确实很别出心裁,一般遇到字符串处理的时候,大部分都是各种逻辑判断加分支等,很难想到用正则表达式来做这个。
毕竟正则表达式在大多数时候,都是用来限制用户输入了。

下面解释一下上面的正则表达式:
首先是(.)这个东西是干嘛的呢?
我们知道.在正则表达式中,就是匹配任意字符的意思。
至于外面的括号,就是把这个看成一个“组”
后面的\\1又代表什么呢?
我们前面用括号分了一个组,这个\\1就是为了获得这个组匹配出的字符,换个词就是,捕获第一个组匹配出的字符。
那么$1又代表什么呢?
这个代表将你前面捕获的字符,拿过来。
所以我们因为(.)任意匹配到一个字符“c“,然后我们后面跟着连续两个\\1将这个正则表达式,动态的变成了”ccc“,自然就会去匹配到”ccc“的字符串。
然后我们通过$1$1,将我们要替换的字符串,动态的变成了”cc“,自然就实现了从”ccc“到”cc“的转变。

第二个同理,只不过\\2就是第二个组的意思,也就是第二个(.),如果将第二个正则表达式的\\2变成\\1就相当于匹配AABA的样式了。
至于$2自然也是同理。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值