Подтвердить что ты не робот

Найти "одну букву, которая появляется дважды" в строке

Я пытаюсь поймать, если одна буква, которая появляется дважды в строке с использованием 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', то только catch:

abbbcppq
 ^^  ^^

Таким образом, выход:

['bb', 'pp']

Затем, если он 'abbbbcppq', дважды поймайте bb:

abbbbcppq
 ^^^^ ^^

Таким образом, выход:

['bb', 'bb', 'pp']
4b9b3361

Ответ 1

Вам нужно использовать регулярное выражение для группы привязки и определить ваше регулярное выражение как необработанную строку.

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

Ответ 2

Как питонический способ Вы можете использовать функцию 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']

Обратите внимание, что re.I - это флаг IGNORECASE, который также делает RegEx соответственно заглавными буквами.

Ответ 3

Используя обратную ссылку, это очень просто:

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 раз

Ответ 4

Возможно, вы можете использовать генератор для достижения этого

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

Ответ 5

Это довольно легко без регулярных выражений:

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

Ответ 6

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

Ответ 7

"или, может быть, есть несколько лучших способов"

Так как регулярное выражение часто неправильно понимается следующим разработчиком, чтобы встретить ваш код (возможно, даже вы), И так как проще!= Короче,

Как насчет следующего псевдокода:

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

Ответ 8

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