2
votes

trouver des mots composés de caractères répétés en python

Clause de non-responsabilité: j'ai trouvé pas mal de questions similaires, mais pas la plus précise. Une fois que quelqu'un a répondu, je le supprimerai.

Je dois trouver tous les mots masqués tels que:

AAAAA aime les pommes, mais BBBBB aime les bananes. Leurs numéros de téléphone sont ffffr et ggggh.

Le motif est au moins trois fois un caractère répété.

Quand j'utilise:

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

J'obtiens simplement tous les mots (qui contiennent plus de 3 caractères).

Idéalement, je ne devrais obtenir que:

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.')

Comment dois-je changer les règles de rage pour n'en capturer que celles-ci?

Merci !


0 commentaires

3 Réponses :


3
votes

Votre regex actuelle vérifie simplement trois [a-z] ou plus, mais pas de répétition. Pour vérifier si une lettre est répétée, vous devez capturer et backreference plus tard. Utilisation de votre re.IGNORECASE

\b\w*?([a-z])\1\1\w*\b
  • \ b correspond à une limite de mots li>
  • \ w correspond à un caractère de mot li>
  • ([a-z]) capture un caractère alphabétique en \1
  • \ 1 est une référence arrière à ce qui est capturé par le premier groupe

Voir la démo sur regex101

Ce serait correspond à au moins 3 [az] répétés entourés de n'importe quelle quantité de \ w caractères de mot.


2 commentaires

Merci! Je pensais qu'il devrait y avoir une solution beaucoup plus simple, mais je dois absolument mieux me renseigner sur les regex.


@ArnoldKlein Bienvenue! J'ai eu le temps d'ajouter un peu plus d'explications. Heureux que cela ait aidé =)



1
votes

Ici, si nous souhaitons capturer un mot, nous utiliserions une limite de mot avec un back-référencement avec une expression similaire à:

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

Démo

Test

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

Circuit RegEx h3>

jex.im visualise les expressions régulières:

 entrez la description de l'image ici


0 commentaires

1
votes

Vous pouvez utiliser une expression régulière, mais je suggère d'utiliser une autre méthode, à savoir:

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

Notez que maintenant found n'est pas exactement le même que votre sortie souhaitée, car de . dans le dernier élément, mais nous pourrions facilement supprimer toute ponctuation de fin de la manière suivante:

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

Explication de ma méthode: j'obtiens 3 premiers caractères de mot, mettez-les tous en minuscules, puis utilisez set pour vérifier s'il n'y a qu'une seule lettre (caractère). Vous pouvez également utiliser la méthode .upper de str . N'hésitez pas à utiliser une solution basée sur les regex si vous la jugez mieux adaptée à votre cas d'utilisation, mais gardez à l'esprit qu'il existe une possibilité de solution non-regex pour certains problèmes.


1 commentaires

Intéressant! Je vais essayer.