例如我有字符串:
aacbbbqq
结果我想要以下匹配:
(aa, c, bbb, qq)
我知道我可以写这样的东西:
([a]+)|([b]+)|([c]+)|...
但我觉得我很丑,正在寻找更好的解决方案。我正在寻找正则表达式解决方案,而不是自己编写的有限状态机。
您可以将其与:
(\w)\1*
匹配
itertools.groupby
不是RexExp,但也不是自己编写的。 :-) 来自 python 文档的引用:
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
技巧是匹配所需范围内的单个字符,然后确保匹配同一字符的所有重复:
>>> matcher= re.compile(r'(.)\1*')
这会匹配任何单个字符 (
.
),然后匹配其重复字符 (\1*
)(如果有)。
对于您的输入字符串,您可以获得所需的输出:
>>> [match.group() for match in matcher.finditer('aacbbbqq')]
['aa', 'c', 'bbb', 'qq']
注意:由于匹配组的原因,
re.findall
将无法正常工作。
如果您不想匹配任何字符,请相应更改正则表达式中的
.
:
>>> matcher= re.compile(r'([a-z])\1*') # only lower case ASCII letters
>>> matcher= re.compile(r'(?i)([a-z])\1*') # only ASCII letters
>>> matcher= re.compile(r'(\w)\1*') # ASCII letters or digits or underscores
>>> matcher= re.compile(r'(?u)(\w)\1*') # against unicode values, any letter or digit known to Unicode, or underscore
对照
u'hello²²'
(Python 2.x) 或 'hello²²'
(Python 3.x) 检查后者:
>>> text= u'hello=\xb2\xb2'
>>> print('\n'.join(match.group() for match in matcher.finditer(text)))
h
e
ll
o
²²
如果您首先发出 \w
调用,则locale.setlocale
针对非 Unicode 字符串/字节数组可能会被修改。
这可以工作,请参阅此处的工作示例:http://www.rubular.com/r/ptdPuz0qDV
(\w)\1*
如果您像这样捕获反向引用,则 findall 方法将起作用:
result = [match[1] + match[0] for match in re.findall(r"(.)(\1*)", string)]
您可以使用:
re.sub(r"(\w)\1*", r'\1', 'tessst')
输出将是:
'test'
你可以尝试这样的事情:
import re
string = 'aacbbbqq'
result = re.findall(r'((\w)\2*?)', string)
output = [x[0] for x in result]
print(output)
输出将是:
['aa', 'c', 'bbb', 'qq']
这个原始解决方案可能有用..
string ="helllllo worlddd hhiii "
i=0
j=1
b=''
l=[]
for a in range(len(string)-1):
if string[i] != string[j]:
j=j+1
i=j-1
if b:
l.append(b)
b=''
elif string[i] == string[j]:
if j-i ==1:`enter code here`
b+=string[i:j+1]
else:
b+=string[i]
j=j+1
print(l)
output:
['lllll', 'ddd', 'hh', 'iii']