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