我试图捕获一个字母在一个字符串中出现两次使用RegEx(或者可能有更好的方法?),例如我的字符串是:
ugknbfddgicrmopn
输出将是:
dd
但是,我尝试过类似的东西:
re.findall('[a-z]{2}', 'ugknbfddgicrmopn')
但在这种情况下,它返回:
['ug', 'kn', 'bf', 'dd', 'gi', 'cr', 'mo', 'pn'] # the except output is `['dd']`
我也有办法获得期望输出:
>>> l = [] >>> tmp = None >>> for i in 'ugknbfddgicrmopn': ... if tmp != i: ... tmp = i ... continue ... l.append(i*2) ... ... >>> l ['dd'] >>>
但那太复杂了......
如果是'abbbcppq'
,那么只抓住:
abbbcppq ^^ ^^
所以输出是:
['bb', 'pp']
然后,如果是的话'abbbbcppq'
,抓bb
两次:
abbbbcppq ^^^^ ^^
所以输出是:
['bb', 'bb', 'pp']
Avinash Raj.. 50
您需要使用基于捕获组的正则表达式并将正则表达式定义为原始字符串.
>>> re.search(r'([a-z])\1', 'ugknbfddgicrmopn').group() 'dd' >>> [i+i for i in re.findall(r'([a-z])\1', 'abbbbcppq')] ['bb', 'bb', 'pp']
要么
>>> [i[0] for i in re.findall(r'(([a-z])\2)', 'abbbbcppq')] ['bb', 'bb', 'pp']
请注意,re.findall
这里应返回元组列表,其中第一个组匹配的字符为第一个元素,第二个组为第二个元素.对于我们的情况,第一组中的字符就足够了所以我提到了i[0]
.
您需要使用基于捕获组的正则表达式并将正则表达式定义为原始字符串.
>>> re.search(r'([a-z])\1', 'ugknbfddgicrmopn').group() 'dd' >>> [i+i for i in re.findall(r'([a-z])\1', 'abbbbcppq')] ['bb', 'bb', 'pp']
要么
>>> [i[0] for i in re.findall(r'(([a-z])\2)', 'abbbbcppq')] ['bb', 'bb', 'pp']
请注意,re.findall
这里应返回元组列表,其中第一个组匹配的字符为第一个元素,第二个组为第二个元素.对于我们的情况,第一组中的字符就足够了所以我提到了i[0]
.
作为Pythonic方式您可以zip
在列表理解中使用函数:
>>> s = 'abbbcppq' >>> >>> [i+j for i,j in zip(s,s[1:]) if i==j] ['bb', 'bb', 'pp']
如果你正在处理大字符串,你可以使用iter()
函数将字符串转换为迭代器并用于itertols.tee()
创建两个独立的迭代器,然后通过调用next
第二个迭代器上的函数消耗第一个项目并使用调用zip
类(在Python 2.X中使用)itertools.izip()
使用此迭代器返回迭代器).
>>> from itertools import tee >>> first = iter(s) >>> second, first = tee(first) >>> next(second) 'a' >>> [i+j for i,j in zip(first,second) if i==j] ['bb', 'bb', 'pp']
RegEx
配方基准:
# ZIP ~ $ python -m timeit --setup "s='abbbcppq'" "[i+j for i,j in zip(s,s[1:]) if i==j]" 1000000 loops, best of 3: 1.56 usec per loop # REGEX ~ $ python -m timeit --setup "s='abbbcppq';import re" "[i[0] for i in re.findall(r'(([a-z])\2)', 'abbbbcppq')]" 100000 loops, best of 3: 3.21 usec per loop
如果您只想匹配一对b
in字符串,就像"abbbcppq"
您可以使用的那样finditer()
返回匹配对象的迭代器,并使用group()
方法提取结果,那么在注释中提到的最后一次编辑之后:
>>> import re >>> >>> s = "abbbcppq" >>> [item.group(0) for item in re.finditer(r'([a-z])\1',s,re.I)] ['bb', 'pp']
注意,这re.I
是IGNORECASE标志,它使RegEx也匹配大写字母.
使用反向引用,非常简单:
import re p = re.compile(ur'([a-z])\1{1,}') re.findall(p, u"ugknbfddgicrmopn") #output: [u'd'] re.findall(p,"abbbcppq") #output: ['b', 'p']
有关更多详细信息,您可以在perl中引用类似的问题:正则表达式匹配任何重复的字符超过10次
没有正则表达式很容易:
In [4]: [k for k, v in collections.Counter("abracadabra").items() if v==2] Out[4]: ['b', 'r']