如何使用正则表达式去除重复的连续字符并保留第一个?

4

我发现了一个从网络上获取的Python代码片段,可以通过正则表达式去除重复连续字符并保留第一个字符,如下:

import re
re.sub(r'(?s)(.)(?=.*\1)','','aabbcc')  #'abc'

但存在一个缺陷,如果字符串是'aabbccaabb',它将忽略第一个'aa'和'bb',输出结果为'cab'。

re.sub(r'(?s)(.)(?=.*\1)','','aabbccaabb')  #'cab'

有没有用正则表达式解决这个问题的方法?
2个回答

4

使用列表推导式和条件来检查前一个字符是否与当前字符相同,而不使用正则表达式,并连接结果:

s='aabbccaabb'
print("".join([c for i,c in enumerate(s) if i==0 or s[i-1]!=c]))

漂亮的 Pythonic 方法。谢谢。 - Haohu Shen
1
类似的:z=list(s); t="".join([u for u,v in zip(z,['']+z)if u!=v])。这避免了循环中的双重测试,但代价是将字符串转换为列表并创建第二个列表,尽管大部分工作都以C速度完成,因此非常快。如果我们知道s永远不会以NUL字符开头,我们可以通过t="".join([u for u,v in zip(s,'\0'+s)if u!=v])来避免转换为列表,但我想那有点笨拙。 ;) - PM 2Ring
@PM2Ring 我总是忘记那个移位的zip操作。谢谢提醒,我会记住的。 - Jean-François Fabre
1
还有s[0]+"".join([c for i,c in enumerate(s[1:]) if s[i]!=c]) - Jean-François Fabre
@PM2Ring uvloop 很不错 :) - Mohammad Yusuf

2

只需去掉正向先行断言中的.*

import re

print re.sub(r'(?s)(.)(?=\1)','','aabbcc')
print re.sub(r'(?s)(.)(?=\1)','','aabbccaabb')

输出:

abc
abcab

2
re.sub(r'(?s)(.)\1', r'\1', 'aabbccaabb') - Scott Carpenter
@ScottCarpenter 它只对重复2个字符的情况有效,对于超过2个字符的情况无效。 - Mohammad Yusuf
1
@ScottCarpenter re.sub(r'(.)\1+', r'\1', 'aaabbccaabb') 这个会起作用。 - Mohammad Yusuf
@Harrison 重复的反斜杠应该替换为1个还是不替换? - Mohammad Yusuf
我的错,代码是正确的。我忘记打印re.sub的结果了。 - Haohu Shen
显示剩余2条评论

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