当前位置:  开发笔记 > 编程语言 > 正文

在字符串中找到"出现两次的一个字母"

如何解决《在字符串中找到"出现两次的一个字母"》经验,为你挑选了4个好方法。

我试图捕获一个字母在一个字符串中出现两次使用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].



1> Avinash Raj..:

您需要使用基于捕获组的正则表达式并将正则表达式定义为原始字符串.

>>> 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].


@KevinGuan ya,确切地说......`()`叫做捕获组.所以`([az])`捕获第一个字母,后面的`\ 1`是对第一个捕获组的反向引用.所以`\ 1`指的是第一组匹配的所有字符.

2> Kasramvd..:

作为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

如果您只想匹配一对bin字符串,就像"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.IIGNORECASE标志,它使RegEx也匹配大写字母.


@Kasramvd:性能不是一切,在这种情况下很可能无关紧要.Regexps是解决问题的工具,它们可以清晰简明地解决这个问题.
在分析程序并确定哪些部分是瓶颈时,性能非常重要.在这种情况下,绝对没有理由关注性能.因此,可读性应该是主要因素,在这种情况下这是完全主观的.
那.因为这里没有理由使用正则表达式.
@ njzk2:一个很好的理由是,这不符合OP对字符串`abbbc`的要求(例如`['bb']`用于regexp vs` ['bb','bb']`这个代码) .

3> Gurupad Hegd..:

使用反向引用,非常简单:

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次


`\ 1 {1,}`将被写为`\ 1 +`

4> Dima Tisnek..:

没有正则表达式很容易:

In [4]: [k for k, v in collections.Counter("abracadabra").items() if v==2]
Out[4]: ['b', 'r']

推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有