IT박스

문자열에서 "두 번 나타나는 한 글자"찾기

itboxs 2020. 12. 30. 07:53
반응형

문자열에서 "두 번 나타나는 한 글자"찾기


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

캡처 그룹 기반 정규식을 사용하고 정규식을 원시 문자열로 정의해야합니다.

>>> 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여기서 첫번째 엘리먼트 및 제 소자로서 두 번째 그룹으로서 제 1 그룹과 일치하는 문자 튜플들의 목록을 반환한다. 우리의 경우 첫 번째 그룹 내의 문자로 충분하므로 언급했습니다 i[0].


Python 방식 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것처럼 문자열에 "abbbcppq"사용할 수있는 finditer()일치하는 객체의 반복자를 반환하고, 함께 결과 추출 group()방법 :

>>> import re
>>> 
>>> s = "abbbcppq"
>>> [item.group(0) for item in re.finditer(r'([a-z])\1',s,re.I)]
['bb', 'pp']

Note that re.I is the IGNORECASE flag which makes the RegEx match the uppercase letters too.


Using back reference, it is very easy:

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

For more details, you can refer to a similar question in perl: Regular expression to match any character being repeated more than 10 times


It is pretty easy without regular expressions:

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

Maybe you can use the generator to achieve this

def adj(s):
    last_c = None
    for c in s:
        if c == last_c:
            yield c * 2
        last_c = c

s = 'ugknbfddgicrmopn'
v = [x for x in adj(s)]
print(v)
# output: ['dd']

"or maybe there's some better ways"

Since regex is often misunderstood by the next developer to encounter your code (may even be you), And since simpler != shorter,

How about the following pseudo-code:

function findMultipleLetters(inputString) {        
    foreach (letter in inputString) {
        dictionaryOfLettersOccurrance[letter]++;
        if (dictionaryOfLettersOccurrance[letter] == 2) {
            multipleLetters.add(letter);
        }
    }
    return multipleLetters;
}
multipleLetters = findMultipleLetters("ugknbfddgicrmopn");

A1 = "abcdededdssffffccfxx"

print A1[1]
for i in range(len(A1)-1):
    if A1[i+1] == A1[i]:
        if not A1[i+1] == A1[i-1]:
            print A1[i] *2

>>> l = ['ug', 'kn', 'bf', 'dd', 'gi', 'cr', 'mo', 'pn']
>>> import re
>>> newList = [item for item in l if re.search(r"([a-z]{1})\1", item)]
>>> newList
['dd']

ReferenceURL : https://stackoverflow.com/questions/34261346/find-one-letter-that-appears-twice-in-a-string

반응형