首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在字符串中查找“一个出现两次的字母”

在字符串中查找“一个出现两次的字母”
EN

Stack Overflow用户
提问于 2015-12-14 15:00:09
回答 8查看 10.3K关注 0票数 58

我正在尝试使用RegEx捕捉一个字符串中出现两次的字母(或许还有更好的方法?),例如,我的字符串是:

代码语言:javascript
运行
复制
ugknbfddgicrmopn

输出将为:

代码语言:javascript
运行
复制
dd

但是,我尝试了一些类似的方法:

代码语言:javascript
运行
复制
re.findall('[a-z]{2}', 'ugknbfddgicrmopn')

但在本例中,它返回:

代码语言:javascript
运行
复制
['ug', 'kn', 'bf', 'dd', 'gi', 'cr', 'mo', 'pn']   # the except output is `['dd']`

我还有一种方法可以获得期望的输出:

代码语言:javascript
运行
复制
>>> l = []
>>> tmp = None
>>> for i in 'ugknbfddgicrmopn':
...     if tmp != i:
...         tmp = i
...         continue
...     l.append(i*2)
...     
... 
>>> l
['dd']
>>> 

但那太复杂了..。

如果是'abbbcppq',那么只捕获:

代码语言:javascript
运行
复制
abbbcppq
 ^^  ^^

因此,输出结果为:

代码语言:javascript
运行
复制
['bb', 'pp']

然后,如果是'abbbbcppq',则捕获bb两次:

代码语言:javascript
运行
复制
abbbbcppq
 ^^^^ ^^

因此,输出结果为:

代码语言:javascript
运行
复制
['bb', 'bb', 'pp']
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2015-12-14 15:13:43

您需要使用基于捕获组的regex,并将您的regex定义为原始字符串。

代码语言:javascript
运行
复制
>>> re.search(r'([a-z])\1', 'ugknbfddgicrmopn').group()
'dd'
>>> [i+i for i in re.findall(r'([a-z])\1', 'abbbbcppq')]
['bb', 'bb', 'pp']

代码语言:javascript
运行
复制
>>> [i[0] for i in re.findall(r'(([a-z])\2)', 'abbbbcppq')]
['bb', 'bb', 'pp']

注意,这里的re.findall应该返回元组列表,其中第一个组匹配的字符是第一个元素,第二个组匹配的是第二个元素。对于我们的案例,第一组中的字符就足够了,所以我提到了i[0]

票数 51
EN

Stack Overflow用户

发布于 2015-12-14 15:03:36

作为一种Pythonic式的方式,您可以在列表理解中使用zip函数:

代码语言:javascript
运行
复制
>>> s = 'abbbcppq'
>>>
>>> [i+j for i,j in zip(s,s[1:]) if i==j]
['bb', 'bb', 'pp']

如果您正在处理大字符串,您可以使用iter()函数将字符串转换为迭代器,并使用itertols.tee()创建两个独立的迭代器,然后通过在第二个迭代器上调用next函数来消费第一个项目,并使用此迭代器调用zip类(在Python2.x中,使用返回迭代器的itertools.izip() )。

代码语言:javascript
运行
复制
>>> 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配方的基准测试:

代码语言:javascript
运行
复制
# 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

在注释中提到的最后一次编辑之后,如果你想只匹配像"abbbcppq"这样的字符串中的一对b,你可以使用finditer(),它返回匹配对象的迭代器,并使用group()方法提取结果:

代码语言:javascript
运行
复制
>>> 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也匹配大写字母。

票数 32
EN

Stack Overflow用户

发布于 2015-12-14 15:08:25

使用反向引用非常简单:

代码语言:javascript
运行
复制
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中的类似问题:Regular expression to match any character being repeated more than 10 times

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34261346

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档