найти слова, состоящие из повторяющихся символов в Python - PullRequest
2 голосов
/ 06 июня 2019

Отказ от ответственности: я нашел довольно много похожих вопросов, но не конкретный. Когда кто-нибудь ответит, я его удалю.

Мне нужно найти все замаскированные слова, такие как:

AAAAA любит яблоки, но BBBBB любит бананы. Их номера телефонов ffffr и ggggh.

Шаблон - как минимум три раза повторяющегося символа.

Когда я использую:

import re

p = re.compile(r'[a-z]{3,}, re.IGNORECASE)
m = p.findall('AAAAA likes apples, but BBBBB likes bananas. Their phone numbers are ffffr and ggggh.')

Я получаю просто все слова (которые содержат более 3 символов).

В идеале я должен получить только:

m = ['AAAAA', 'BBBBB', 'ffffr', 'ggggh']

Как мне изменить правила ярости, чтобы захватывать только те?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 06 июня 2019

Ваше текущее регулярное выражение просто проверяет три или более [a-z], но не повторяет.Чтобы проверить, повторяется ли письмо, вам нужно захватить и обратную ссылку позже.Использование re.IGNORECASE

\b\w*?([a-z])\1\1\w*\b
  • \b соответствует границе слова
  • \w соответствует символу слова
  • ([a-z]) захватывает буквенный символ для \1
  • \1 является обратной ссылкой на то, что было захвачено первой группой

См. Демонстрацию вregex101

Это будет соответствовать как минимум 3 повторным [a-z], окруженным любым количеством \w символов слова.

1 голос
/ 06 июня 2019

Вы можете использовать регулярные выражения, но я предлагаю использовать другой способ, а именно:

txt = 'AAAAA likes apples, but BBBBB likes bananas. Their phone numbers are ffffr and ggggh.'
words = txt.split(' ')
found = [i for i in words if len(set(i[:3].lower()))==1]
print(found) # ['AAAAA', 'BBBBB', 'ffffr', 'ggggh.']

Обратите внимание, что теперь found не совсем соответствует желаемому результату из-за . в последнем элементе, но мы могли бы легко удалить любую конечную пунктуацию следующим образом:

import string
clear_found = [i.rstrip(string.punctuation) for i in found]
print(clear_found) # ['AAAAA', 'BBBBB', 'ffffr', 'ggggh']

Объяснение моего метода: я получаю 3 первых символа слова, перевожу их все в нижний регистр, затем использую set, чтобы проверить, есть ли только одна буква (символ). В качестве альтернативы вы можете использовать .upper метод str. Не стесняйтесь использовать решение на основе регулярных выражений, если считаете, что оно лучше подходит для вашего варианта использования, но имейте в виду, что для определенных проблем существует возможность решения без регулярных выражений.

1 голос
/ 06 июня 2019

Здесь, если мы хотим захватить слово, мы будем использовать границу слова с обратными ссылками с выражением, похожим на:

\b([a-z])\1\1\1.+?\b

Демо

Тест

# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility

import re

regex = r"\b([a-z])\1\1\1.+?\b"

test_str = "AAAAA likes apples, but BBBBB likes bananas. Their phone numbers are ffffr and ggggh."

matches = re.finditer(regex, test_str, re.MULTILINE | re.IGNORECASE)

for matchNum, match in enumerate(matches, start=1):

    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1

        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))

# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.

Схема RegEx

jex.im визуализирует регулярные выражения:

enter image description here

...